[bfs][状压] Jzoj P2121 分球
题解
- 可以直接用bfs来做,范围小
- 那么对于普通的dfs,会死循环,考虑如果解决这个问题
- 我们想到对于一个格子只可能有三种情况:金、银、空
- 那么我们可以用一个三进制数来压缩状态
- 这样就可以A了
代码
1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 #include <cstring> 5 using namespace std; 6 int k,n,head,tail,x,p,f[16*100000],a[16],b[16],w[100000][16]; 7 char ch; 8 bool check(int *x) 9 { 10 int y=0; 11 for (int i=1;i<=n+1;i++) 12 { 13 y+=x[i]&1; 14 if (y==n-1) return 1; 15 if (x[i]==2) return 0; 16 } 17 } 18 void change(int *x) 19 { 20 int o=0; p=0; 21 for (int i=1;i<=2*n;i++) 22 if (x[i]==0&&o==0) o=1; 23 else p=p*3+x[i]; 24 } 25 int bfs() 26 { 27 if (check(w[1])) return 0; 28 head=0; tail=1; 29 change(w[1]); 30 f[p]=k; 31 while (head<tail) 32 { 33 head++; 34 memcpy(a,w[head],sizeof(a)); memcpy(b,a,sizeof(b)); b[0]++; 35 for (int i=1;i<=2*n-1;i++) if (a[i]==0) { x=i; break; } 36 for (int i=1;i<=2*n-1;i++) 37 if (a[i]!=0&&a[i+1]!=0) 38 { 39 b[x]=a[i]; b[x+1]=a[i+1]; b[i]=b[i+1]=0; change(b); 40 if (f[p]!=k) 41 { 42 if (check(b)) return b[0]; 43 tail++; 44 f[p]=k; 45 memcpy(w[tail],b,sizeof(w[tail])); 46 } 47 b[i]=a[i]; b[i+1]=a[i+1]; 48 } 49 } 50 return -1; 51 } 52 int main() 53 { 54 for (scanf("%d",&k);k;k--) 55 { 56 scanf("%d",&n); 57 getchar(); 58 for (int i=1;i<=2*n;i++) 59 { 60 ch=getchar(); 61 w[1][i]=(ch==' '?0:ch-96); 62 } 63 printf("%d\n",bfs()); 64 } 65 }