P9723 [EC Final 2022] Chinese Checker

发布时间 2023-11-14 22:07:17作者: LHLeisus

原题链接

模拟赛出了,赛时被这个六芒星的形状吓住了,感觉被降智了,呜呜。

其实只要转化一下就可以愉快地爆搜了。

可以将这两条线看做坐标轴,然后把整个六芒星的的形状转化成横平竖直的样子,大概长这样(\(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;
	}
}