原题链接:https://vjudge.net/problem/UVA-11694
分类:回溯法
备注:细节,强剪枝,好题
试了好多次也A不了,最后看别人博客感觉细节上更懂了一些,但是没改出来,最后不了了之,还是用了别人的代码。
这里判环的方法可以注意一下,挺不错。
#include<bits/stdc++.h>
using namespace std;
const int dir[][2]={{-1,-1},{1,1},{-1,1},{1,-1}};//左上 右下 右上 左下
const int up[][2]={{0,0},{0,1}};//0位'\' 1为'/'
const int down[][2]={{1,1},{1,0}};
int N,n,cnt[30][30],vis[30][30],edge[30][30][30][30],tag;
char g[30][30],ans[30][30];
inline char read(){
char ch=getchar();
while(ch==' '||ch=='\n')ch=getchar();
return ch;
}
inline bool isLoop(int x,int y,int f){
if(vis[x][y]==tag)return true;
vis[x][y]=tag;
for(int i=0;i<4;i++){
if((i^1)==f)continue;
if(edge[x][y][x+dir[i][0]][y+dir[i][1]])
if(isLoop(x+dir[i][0],y+dir[i][1],i))return true;
}
return false;
}
inline void update(int x1,int y1,int x2,int y2,int op){
if(isdigit(g[x1][y1]))cnt[x1][y1]+=op;
if(isdigit(g[x2][y2]))cnt[x2][y2]+=op;
}
bool dfs(int pos){
if(pos==n*n)return true;
int x=pos/n,y=pos%n;
for(int i=0;i<2;i++){
int ux=x+up[i][0],uy=y+up[i][1];
int dx=x+down[i][0],dy=y+down[i][1];
if(isdigit(g[ux][uy])&&!cnt[ux][uy])continue;
if(isdigit(g[dx][dy])&&!cnt[dx][dy])continue;
update(ux,uy,dx,dy,-1);
if(cnt[x+up[0][0]][y+up[0][1]]>0||//左上角
(y+1==n&&cnt[x+up[1][0]][y+up[1][1]]>0)||//边界右上角
(x+1==n&&cnt[x+down[1][0]][y+down[1][1]]>0)||//下界左下
(x+1==n&&y+1==n&&cnt[x+down[0][0]][y+down[0][1]]>0)){//右下角
update(ux,uy,dx,dy,1); continue;
}
ans[x][y]=i; tag++;
edge[ux][uy][dx][dy]=edge[dx][dy][ux][uy]=1;
if(isLoop(dx,dy,-1)){
edge[ux][uy][dx][dy]=edge[dx][dy][ux][uy]=0;
update(ux,uy,dx,dy,1); continue;
}
if(dfs(pos+1))return true;
edge[ux][uy][dx][dy]=edge[dx][dy][ux][uy]=0;
update(ux,uy,dx,dy,1);
}
return false;
}
int main(void){
//freopen("in.txt","r",stdin);
scanf("%d",&N);
while(N--){
scanf("%d",&n);
memset(edge,0,sizeof(edge));
for(int i=0;i<=n;i++)
for(int j=0;j<=n;j++){
g[i][j]=read();
if(isdigit(g[i][j]))cnt[i][j]=g[i][j]-'0';
}
dfs(0);
for(int i=0;i<n;i++){
for(int j=0;j<n;j++)
printf("%c",ans[i][j]?'/':'\\');
printf("\n");
}
}
return 0;
}