USACO 4.1 Cryptcowgraphy dfs+剪枝

来源:互联网 发布:java应届生简历模板 编辑:程序博客网 时间:2024/06/09 17:36

http://ace.delos.com/usacoprob2?a=2SgXjKYaF1c&S=cryptcow

一道bt的剪枝题,做了一下午,最后还是看了别人的解题报告过的,才菜了。。 。

剪枝1:C,O,W出现的次数要相同,除了C,O,W之外的其他字符串的个数和类型和目标串相同。

剪枝2:通过ELFHash对串进行判重.( HASHSIZE可以大点)

剪枝3:对于任意串, 任意相邻的'C', 'O', 'W'之间的串应该在目标串中能找到.( 很强大的剪枝,没有这个剪枝就死活过不去。。)

剪枝4:枚举C,O,W的时候,先枚举O的位置,再枚举C,最后枚举W,而且W的枚举从后往前枚举。


代码:

/*ID :chrisLANG :C++TASK : cryptcow*/#include <stdio.h>#include <string.h>#include <iostream>#include <string>using namespace std;const int MAXM = 80 ;string ch ;string str = "Begin the Escape execution at the Break of Dawn" ;int a1,a2,a3 ,len;int num[300] ;int stand[300] ;int s_len  ;void calc(){memset(stand , 0 ,sizeof(stand) );for(int i=0;str[i];i++){stand[ str[i] ] ++ ;}}bool is_ok(){for(int i=0;i<300;i++)if(num[i] != stand[i])return false ;return true ;}const int MAXN = 999991 ;bool hash[MAXN];bool f ;int ELFhash(string ch){unsigned long h = 0; for(int i=0;i<ch.size();i++){h = (h << 4) + ch[i] ;unsigned long g = h & 0xf0000000L ;if( g )h ^= g >> 24 ;h &= ~g ;}return h % MAXN ;}void dfs(string ch){if(ch == str){f = 1 ; return ;}int len = ch.size() ;string s ;for(int i=0;i<len;i++){if(ch[i] == 'C')break ;if(str[i] != ch[i])return ;if(ch[i]=='O' || ch[i]=='W')return ;}int end = s_len - 1;for(int i=len-1;i>=0;i--){if(ch[i]=='W')break ;if(ch[i] != str[end--])return ;if(ch[i]=='O' || ch[i]=='C')return  ;}int a = ELFhash(ch) ;if( hash[a] )return ;hash[a] = 1 ;int cnt=0, c_cnt=0 ,o_cnt=0 , w_cnt=0; int c[MAXM] ,o[MAXM] ,w[MAXM] ,label[MAXM] ;memset(c , 0,sizeof(c));memset(o , 0,sizeof(o));memset(w , 0,sizeof(w));memset(label , 0,sizeof(label));for(int i=0;i<len;i++){if( ch[i] == 'C'){c[c_cnt++] = i ;label[cnt++] = i ;}else if( ch[i]=='O'){o[o_cnt++] = i ;label[cnt++] = i ;}else if( ch[i]=='W'){w[w_cnt++] = i ;label[cnt++] = i ;}}label[ cnt++ ] = len ;for(int i=0;i<cnt-1;i++){if(label[i]+1 < label[i+1] ){string sub = ch.substr( label[i]+1 , label[i+1]-1-label[i]) ;if( str.find(sub) == string::npos){return ;}}}for(int i=0;i<o_cnt;i++){for(int j=0;j<c_cnt;j++){for(int k=w_cnt-1;k>=0;k--){if(c[j]<o[i] && o[i]<w[k]){string t1 = ch.substr(0,c[j]);string t2 = ch.substr(o[i]+1,w[k]-o[i]-1);string t3 = ch.substr(c[j]+1,o[i]-c[j]-1);string t4 = ch.substr(w[k]+1,len-w[k]);string t = t1+t2+t3+t4 ;dfs(t);if(f)return ;}}}}}int main(){freopen("cryptcow.in","r",stdin);freopen("cryptcow.out","w",stdout);calc() ;s_len = str.size() ;getline(cin ,ch);a1 = a2 = a3 = 0 ;len = ch.size() ;memset(num , 0 ,sizeof(num));for(int i=0;i<len;i++){if(ch[i] == 'C')a1 ++ ;else if(ch[i] == 'O')a2 ++ ;else if(ch[i] == 'W')a3 ++ ;else num[ ch[i] ] ++ ;}if( is_ok() == 0){printf("0 0\n");return 0 ;}if(a1==0 && a2==0 && a3==0){if( ch == str )printf("1 0\n");elseprintf("0 0\n");return 0 ;}if(a1==a2 && a2==a3){memset(hash , 0 ,sizeof(hash));f = 0 ;dfs(ch) ;if(f)printf("1 %d\n",a1);elseprintf("0 0\n");}else{printf("0 0\n");}return 0 ;}

原创粉丝点击