这个题目的深搜形式,我也找出来了,dfs(i,j)表示第i个人选到了第j个物品,但是我却无限RE了,原因是我的viod型深搜太过暴力,我当时定义了一个计数器,来记录并限制递归的层数,发现它已经递归到了1500层,加上限制后,WA了……后来学习了网上的方法,使用bool型的深搜,每一次选择都去跟题目中给的限制去比较,看这次选择有没有冲突,如果没有搜下一个,当搜到false的时候,及时停止,节省了时间和空间。
伪代码: if(dfs(next)==true) return true; else return false; 这样我们在很有可能在选某一个数的时候,发现已经没有合适方案,及时停止递归,而不是我那种每次都递归到最底层。
注意:我的代码比较短,但是耗时83MS,源代码很长,耗时3MS,区别是判断冲突的方法不一样,读者可以自己思考其他的判定方法,应该还有很多。
再就是我的做了一步优化,我们可以从第二个物品开始选,这样也保证了题目的输出正确。
最后,UVAlive的oj好奇葩,我自己的代码WA时,还感觉很奇怪,后来发现少了换行,它怎么就是不返回PE呢……被坑好多次……
代码如下:
#include<iostream> #include<cstdio> #include<cstring> #include<vector> using namespace std; #define N 10 struct Check{ int a,b,c,d; char op[2]; }ch[2500]; char maps[N][N]; int n,m,cnt,belong[N][N]; bool dfs(int ci,int cj){ int a,b,c,d,flag; char op; if(ci==m+1 && cj == 2){ return true; } for(int i = 1;i <= m;i++){ if(belong[cj][i]) continue; belong[cj][i] = ci; flag = 1; for(int j = 0;j < cnt;j++){ a = ch[j].a; b = ch[j].b; c = ch[j].c; d = ch[j].d; op = ch[j].op[0]; if((!belong[a][b]) || (!belong[c][d])) continue; if(op=='R'&&belong[a][b] != belong[c][d]){ flag = 0; break; } if(op=='N'&&belong[a][b] == belong[c][d]){ flag = 0; break; } } if(!flag){ belong[cj][i] = 0; continue; } if(cj==n){ if(dfs(ci+1,2)) return true; } else if(dfs(ci,cj+1)) return true; belong[cj][i] = 0; } return false; } int main(){ int t; scanf("%d",&t); while(t--){ scanf("%d%d",&n,&m); for(int i = 1;i <= n;i++){ scanf("%s",maps[i]+1); } for(cnt = 0;true;cnt++){ scanf("%d%d%s%d%d",&ch[cnt].a,&ch[cnt].b,ch[cnt].op,&ch[cnt].c,&ch[cnt].d); if(ch[cnt].a == 0){ break; } } memset(belong,0,sizeof(belong)); for(int i = 1;i <= m;i++) belong[1][i] = i; dfs(1,2); for(int i = 1;i <= m;i++){ for(int j = 1;j <= n;j++){ for(int k = 1;k <= m;k++){ if(belong[j][k]==i){ printf("%c",maps[j][k]); } } } printf(" "); } printf(" "); } return 0; }