模拟赛出了,赛时被这个六芒星的形状吓住了,感觉被降智了,呜呜。
其实只要转化一下就可以愉快地爆搜了。
可以将这两条线看做坐标轴,然后把整个六芒星的的形状转化成横平竖直的样子,大概长这样(\(1\) 表示是棋盘):
0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0
0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0
0 0 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0
0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0
0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0
0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0
0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 0 0
0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0
0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
于是就有了以下的初始化代码:
void init(){
FOR(i,5,5) ib[1][i]=1;FOR(i,5,6) ib[2][i]=1;FOR(i,5,7) ib[3][i]=1;FOR(i,5,8) ib[4][i]=1;
FOR(i,1,13) ib[5][i]=1;FOR(i,2,13) ib[6][i]=1;FOR(i,3,13) ib[7][i]=1;FOR(i,4,13) ib[8][i]=1;FOR(i,5,13) ib[9][i]=1;
FOR(i,5,14) ib[10][i]=1;FOR(i,5,15) ib[11][i]=1;FOR(i,5,16) ib[12][i]=1;FOR(i,5,17) ib[13][i]=1;
FOR(i,10,13) ib[14][i]=1;FOR(i,11,13) ib[15][i]=1;FOR(i,12,13) ib[16][i]=1;FOR(i,13,13) ib[17][i]=1;
}
极致的压行()
然后题目要求只能沿着对角线跳,而三条对角线分别被转化成了行、列和左上到右下的对角线。只需要枚举每个棋子,分别沿着三条对角线爆搜就好了,该剪枝就剪,根本跑不满,时间复杂度不是很会算,反正可以 AC()。
搜索的时候要注意一些细节,包括但不限于:
-
沿着对角线搜到第一个棋子后就要返回,因为当前位置和跳过去的位置中间只允许存在一个棋子,就是那个跳板。
-
中间走过的位置及时标记,不能重复走,可能会死循环。并且最终结果不同只与最终状态有关系,所以假如通过不同的方式能够到达同一个点,这个点只会对答案造成一次贡献。
-
起点的棋子也要打上标记,不然有可能跳了一圈回来,从这个点跳走了,但这个棋子已经没了,不能跳。
-
输入的时候也要注意,输入的是在棋盘上的位置,要转化成在整个矩阵里的位置。
其实以上是我踩过的坑,不过大概实现方法不同坑也不一样?所以说坑还得自己踩(逃)
代码仅供参考
点击查看代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<utility>
#include<vector>
#include<queue>
#include<bitset>
#include<map>
#define FOR(i,a,b) for(register int i=a;i<=b;++i)
#define ROF(i,a,b) for(register int i=a;i>=b;--i)
#define mp(a,b) make_pair(a,b)
#define pll pair<long long,long long>
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline int read();
typedef long long ll;
typedef double db;
const int N=1e5+5;
const int INF=0x3f3f3f3f;
int n,m,k;
int ib[20][20],base[20]={0,4,4,4,4,0,1,2,3,4,4,4,4,4,9,10,11,12};
int book[20][20],ans;
bitset<100>vis[100];
void dfs(int x,int y);
void init();
void solve();
int main()
{
init();
int T=read();
while(T--) solve();
return 0;
}
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return f*x;
}
void init(){
FOR(i,5,5) ib[1][i]=1;FOR(i,5,6) ib[2][i]=1;FOR(i,5,7) ib[3][i]=1;FOR(i,5,8) ib[4][i]=1;
FOR(i,1,13) ib[5][i]=1;FOR(i,2,13) ib[6][i]=1;FOR(i,3,13) ib[7][i]=1;FOR(i,4,13) ib[8][i]=1;FOR(i,5,13) ib[9][i]=1;
FOR(i,5,14) ib[10][i]=1;FOR(i,5,15) ib[11][i]=1;FOR(i,5,16) ib[12][i]=1;FOR(i,5,17) ib[13][i]=1;
FOR(i,10,13) ib[14][i]=1;FOR(i,11,13) ib[15][i]=1;FOR(i,12,13) ib[16][i]=1;FOR(i,13,13) ib[17][i]=1;
}
void solve(){
queue<pii>q;
memcpy(book,ib,sizeof ib);ans=0;n=read();
FOR(i,1,n){
int x=read(),y=read();
y+=base[x];book[x][y]=2;
q.push(mp(x,y));
}
FOR(i,0,20) vis[i].reset();
while(!q.empty()){
pii t=q.front();q.pop();
vis[t.fi][t.se]=1;
book[t.fi][t.se]=1;
dfs(t.fi,t.se);
vis[t.fi][t.se]=0;
FOR(i,0,20) vis[i].reset();
book[t.fi][t.se]=2;
}
printf("%d\n",ans);
}
void dfs(int x,int y){
FOR(i,x+1,17){
if(i+i-x>17) break;
if(book[i][y]==2&&i+i-x<=17&&book[i+i-x][y]==1&&!vis[i+i-x][y]){
int t=i+i-x;
while(1){
i++;if(i==t){vis[i][y]=1,dfs(i,y),ans++;break;}
if(book[i][y]!=1) break;
}
break;
}
else if(book[i][y]!=1) break;
}
ROF(i,x-1,1){
if(i+i-x<1) break;
if(book[i][y]==2&&i+i-x>=1&&book[i+i-x][y]==1&&!vis[i+i-x][y]){
int t=i+i-x;
while(1){
i--;if(i==t){vis[i][y]=1,dfs(i,y),ans++;break;}
if(book[i][y]!=1) break;
}
break;
}
else if(book[i][y]!=1) break;
}
FOR(j,y+1,17){
if(j+j-y>17) break;
if(book[x][j]==2&&j+j-y<=17&&book[x][j+j-y]==1&&!vis[x][j+j-y]){
int t=j+j-y;
while(1){
j++;if(j==t){vis[x][j]=1,dfs(x,j),ans++;break;}
if(book[x][j]!=1) break;
}
break;
}
else if(book[x][j]!=1) break;
}
ROF(j,y-1,1){
if(j+j-y<1) break;
if(book[x][j]==2&&j+j-y>=1&&book[x][j+j-y]==1&&!vis[x][j+j-y]){
int t=j+j-y;
while(1){
j--;if(j==t){vis[x][j]=1,dfs(x,j),ans++;break;}
if(book[x][j]!=1) break;
}
break;
}
else if(book[x][j]!=1) break;
}
for(int i=x+1,j=y+1;i<=17&&j<=17;++i,++j){
if(i+i-x>17||j+j-y>17) break;
if(book[i][j]==2&&i+i-x<=17&&j+j-y<=17&&book[i+i-x][j+j-y]==1&&!vis[i+i-x][j+j-y]){
int tx=i+i-x,ty=j+j-y;
while(1){
++i,++j;if(i==tx&&j==ty){vis[i][j]=1,dfs(i,j),ans++;break;}
if(book[i][j]!=1) break;
}
break;
}
else if(book[i][j]!=1) break;
}
for(int i=x-1,j=y-1;i>=1&&j>=1;--i,--j){
if(i+i-x<1||j+j-y<1) break;
if(book[i][j]==2&&i+i-x>=1&&j+j-y>=1&&book[i+i-x][j+j-y]==1&&!vis[i+i-x][j+j-y]){
int tx=i+i-x,ty=j+j-y;
while(1){
--i,--j;if(i==tx&&j==ty){vis[i][j]=1,dfs(i,j),ans++;break;}
if(book[i][j]!=1) break;
}
break;
}
else if(book[i][j]!=1) break;
}
}