这道题有两种做法:搜索和状态压缩dp
因为这个题的状态只要2^12,所以可以用dfs或bfs将所有的可达状态走一遍,然后就可以得到答案了。
我是用二进制压缩以后再进行的dfs;其实也可以直接开一个12位长度数组表示状态,然后dfs或bfs,这样
状态判重可以用hash或二进制压缩。
状态压缩dp的话,现在还没看,就放到以后再研究去了。
代码如下:
#include<iostream> #include<cstring> #include<cstdio> using namespace std; int vis[5000],ans; void dfs(int st) { int a[20]; int k=0; memset(a,0,sizeof(a)); while(st) { a[k++]=st%2; st/=2; } k=12; for(int i=k-1;i>=2;i--) { if(a[i]==0&&a[i-1]==1&&a[i-2]==1) { int b[30]; for(int j=0;j<k;j++) b[j]=a[j]; b[i]=1; b[i-1]=0; b[i-2]=0; int cnt=0,sum=0; for(int j=k-1;j>=0;j--) { if(b[j]==1) cnt++; if(b[j]==1) sum=sum*2+1; else sum=sum*2; } if(cnt!=0&&cnt<ans) ans=cnt; if(vis[sum]==0) { vis[sum]=1; dfs(sum); } } } for(int i=0;i<k-2;i++) { if(a[i]==0&&a[i+1]==1&&a[i+2]==1) { int b[30]; for(int j=0;j<k;j++) b[j]=a[j]; b[i]=1; b[i+1]=0; b[i+2]=0; int cnt=0,sum=0; for(int j=k-1;j>=0;j--) { if(b[j]==1) cnt++; if(b[j]==1) sum=sum*2+1; else sum=sum*2; } if(cnt!=0&&cnt<ans) ans=cnt; if(vis[sum]==0) { vis[sum]=1; dfs(sum); } } } } int main() { int n; scanf("%d",&n); while(n--) { ans=0; char str[20]; scanf("%s",str); int len=strlen(str); int st=0; for(int i=0;i<len;i++) { if(str[i]=='o') ans++; if(str[i]=='o') st=st*2+1; else st=st*2; } memset(vis,0,sizeof(vis)); vis[st]=1; dfs(st); printf("%d\n",ans); } return 0; }
UVA 10651 --Pebble Solitaire +dfs
原文地址:http://blog.csdn.net/acm_lkl/article/details/43117551