标签:rgb print ble blank c_str 序列 color nbsp href
考察:状压dp+dfs寻找路径
思路:
重复覆盖问题.参考愤怒的小鸟的思路,我们需要两两构造一个包含两个字符串a,b的DNA序列,然后要分a在前面与b在前面两种情况.
本蒟蒻一开始想的是定义结构体String,再定义结构体内部的st(二进制标记哪些串被标记),构造后的具体字符串s.每个状态f都要记录当前状态的最优字符串.但实际上没必要.这道题是属于倒序输出具体方案.并且本道题并不需要构造具体字符串,因为构造后的字符串含有字符串a,b,c....如果构造后能包含字符串d,说明a,b,c就存在一个字符串能包含d或被d包含.所以一定不存在构造新字符串后还能包含某个其他字符串的情况.
所以可以定义f[i][j]为i状态下,首字符串为j的最短长度.f[i][j] = f[i-(1<<j)][k]+cost[j][k](表示把j放在k前面的花费).可用unique去掉被包含的字符串.
计算cost就是后缀匹配前缀...可以用substr计算,不记得建议复习单词接龙这道题....
最后倒序输出方案的时候,不一定是在前面的字典序一定最小,比如当前后缀CAAB 匹配它的AABX与ABC.按排序是AABX在前,但是接ABC字典序更小.所以需要去掉重叠部分比较.
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <algorithm> 5 using namespace std; 6 const int N = 15,M = 110; 7 int n,cost[N][N],f[1<<N][N];//cost[i][j]表示将i放在j前面的花费 8 string s[N],res;//重复覆盖问题 9 void init()//前后缀匹配 :substr 10 { 11 memset(cost,0,sizeof cost); 12 for(int i=0;i<n;i++) 13 for(int j=0;j<n;j++) 14 if(s[i].find(s[j])!=s[i].npos) s[j] = s[i]; 15 sort(s,s+n);//按序号字典序最小 16 n = unique(s,s+n)-s;//去掉没必要存在的s 17 for(int i=0;i<n;i++) 18 for(int j=0;j<n;j++) 19 { 20 if(i==j) continue; 21 int sz = min(s[i].size(),s[j].size()),k; 22 for(k=sz;k>=0;k--) 23 if(s[i].substr(s[i].size()-k,k)==s[j].substr(0,k)) 24 { 25 cost[i][j] = s[i].size()-k; 26 break; 27 } 28 } 29 } 30 void solve() 31 { 32 memset(f,0x3f,sizeof f); 33 for(int i=0;i<n;i++) f[1<<i][i] = s[i].size(); 34 for(int i=1;i<1<<n;i++) 35 for(int j=0;j<n;j++) 36 if(i>>j&1) 37 for(int k=0;k<n;k++) 38 if(j!=k&&(i>>k&1)) 39 f[i][j] = min(f[i-(1<<j)][k]+cost[j][k],f[i][j]); 40 } 41 void dfs(int st,int idx) 42 { 43 if(!st) return; 44 int now = st-(1<<idx),v = -1; 45 string temp = "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"; 46 for(int i=0;i<n;i++) 47 if((now>>i&1)&&f[now][i]+cost[idx][i]==f[st][idx]) 48 { 49 string t = s[i].substr(s[idx].size()-cost[idx][i]); 50 if(t<temp) 51 temp = t,v = i; 52 } 53 if(v!=-1) 54 { 55 res+=temp; 56 dfs(now,v); 57 } 58 } 59 int main() 60 { 61 int T,kcase = 0; 62 scanf("%d",&T); 63 while(T--) 64 { 65 if(kcase) printf("\n"); 66 scanf("%d",&n); 67 for(int i=0;i<n;i++) cin>>s[i]; 68 init(); 69 solve(); 70 int ans = 0x3f3f3f3f; 71 for(int i=0;i<n;i++) ans = min(ans,f[(1<<n)-1][i]); 72 for(int i=0;i<n;i++) 73 if(f[(1<<n)-1][i]==ans) 74 { 75 res = s[i]; 76 dfs((1<<n)-1,i); 77 break; 78 } 79 printf("Scenario #%d:\n%s\n",++kcase,res.c_str()); 80 } 81 return 0; 82 }
标签:rgb print ble blank c_str 序列 color nbsp href
原文地址:https://www.cnblogs.com/newblg/p/14615662.html