一道很简单的题目,但是写的时候莫名奇妙小错误不断很坑爹 用sum前缀和 相减表示最小步数剪枝 同时 可以自交的意思是路线上可以相交,但是不可以停在同一个点 这有点坑爹啊 因为有负坐标 把负的全部映射成正的 大于 (1+n)*n/2的一半的肯定返回不了了,这种障碍点可以直接去掉不用管
#include<bits/stdc++.h>
using namespace std;
const int add=115;
const int maxn=300;
int vis[maxn][maxn];
int mp[maxn][maxn];
int cnt;
int sum[25];
int ans[300];
int dx[]={1,0,0,-1};
int dy[]={0,1,-1,0};
char sign[]="ensw";
int k;
bool check(int x,int y,int bushu,int faxiang){
for(int i=0;i<bushu;i++){
x+=dx[faxiang];
y+=dy[faxiang]; //走的过程中如果碰到障碍肯定不行
if(mp[x][y]==-1)return 0;
}
if(abs(x-add)+abs(y-add)>sum[k]-sum[bushu])return 0; //最大步数都返回不了,剪去
return 1;
}
void dfs(int x,int y,int d,int last){//x y 坐标 d步数 last是上一次的方向
if(d==k&&x==add&&y==add){
cnt++;
for(int i=0;i<d;i++)
printf("%c",sign[ans[i]]);
printf("\n");
return ;
}
for(int i=0;i<4;i++){
int tx=x+dx[i]*(d+1); //要加1 从0开始的
int ty=y+dy[i]*(d+1);
if(!mp[tx][ty]&&i!=last&&i+last!=3&&!vis[tx][ty]&&check(x,y,(d+1),i)){//不等于上次的方向或者反方向
ans[d]=i;
vis[tx][ty]=1;
dfs(tx,ty,d+1,i);
vis[tx][ty]=0;
}
}
}
int main(){
sum[0] = 0;
for (int i = 1; i <= 20; i++) sum[i] = sum[i-1] + i; //和数组
int t;
scanf("%d",&t);
while(t--){
cnt=0;
memset(vis,0,sizeof(vis));
scanf("%d",&k);
memset(mp,0,sizeof(mp));
int m;
scanf("%d",&m);
for(int i=0;i<m;i++){
int a,b;
scanf("%d%d",&a,&b);
if(abs(a)>maxn||abs(b)>maxn)continue; //平移add
mp[a+add][b+add]=-1;
}
dfs(add,add,0,-1);//刚开始任意方向直接上一个不会和条件冲突的数就好了我选-1我骄傲
printf("Found %d golygon(s).\n\n",cnt);
}
return 0;
}