转载请注明出处,谢谢 http://blog.csdn.net/ACM_cxlove?viewmode=contents by---cxlove
继续IDA*,明显可以想到的一个剪枝是,至少还需要的长度是所有剩余长度的最大值,这样就可以根据深度和估价函数来剪枝,就可以用IDA*了。
开始竟然用状态压缩,枚举状态,果断超时,注释部分就是原先写的,其实每步都是贪心,如果取了某个位置的字母,其它字符串相同字符肯定一起取掉。
这样的话,状态就少了很多,1.6S,还可以。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<cmath>
#include<map>
#include<string>
#define inf 1<<30
#define eps 1e-7
#define LD long double
#define LL long long
#define maxn 1005
using namespace std;
int n,len[8];
int depth;
bool flag;
char dna[8][6];
int get_h(int *l){
int ans=0;
for(int i=0;i<n;i++)
ans=max(ans,l[i]);
return ans;
}
//bool check(int *l,int state){
// int ch=0;
// for(int i=0;i<n;i++)
// if(((1<<i)&state)==0)
// continue;
// else if(l[i]==0)
// return false;
// else if(ch==0||(int)dna[i][len[i]-l[i]]==ch)
// ch=(int)dna[i][len[i]-l[i]];
// else
// return false;
// return true;
//}
void IDAstar(int *l,int tmp_depth){
if(flag)
return;
if(get_h(l)>tmp_depth)
return;
if(tmp_depth==0){
flag=true;
return;
}
bool mark[8];
memset(mark,false,sizeof(mark));
for(int i=0;i<n;i++)
if(mark[i]==false&&l[i]){
int tmp[8];
for(int j=0;j<n;j++)
tmp[j]=l[j];
mark[i]=true;
char ch=dna[i][len[i]-l[i]];
tmp[i]--;
for(int j=i+1;j<n;j++)
if(!mark[j]&&dna[j][len[j]-l[j]]==ch&&l[j]){
mark[j]=true;
tmp[j]--;
}
IDAstar(tmp,tmp_depth-1);
}
/*for(int i=1;i<(1<<n);i++)
if(check(l,i)){
int tmp[8];
for(int i=0;i<8;i++)
tmp[i]=l[i];
for(int j=0;j<n;j++)
if(i&(1<<j))
tmp[j]--;
IDAstar(tmp,tmp_depth-1);
}*/
}
int main(){
int t;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
int low=0;
for(int i=0;i<n;i++){
scanf("%s",dna[i]);
len[i]=strlen(dna[i]);
low=max(low,len[i]);
}
flag=false;
for(depth=low;;depth++){
IDAstar(len,depth);
if(flag){
printf("%d\n",depth);
break;
}
}
}
return 0;
}