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 :chris
LANG :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");
else printf("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);
else printf("0 0\n");
}
else{
printf("0 0\n");
}
return 0 ;
}