P9723 [EC Final 2022] Chinese Checker
模拟赛出了,赛时被这个六芒星的形状吓住了,感觉被降智了,呜呜。
其实只要转化一下就可以愉快地爆搜了。
可以将这两条线看做坐标轴,然后把整个六芒星的的形状转化成横平竖直的样子,大概长这样(\(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; } }
$$\text{看完了不点个赞再走嘛!!!}$$
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现