poj1795(状态压缩dp,字符串压缩求最小字典序)
来源:互联网 发布:爱淘宝天猫购物券口令 编辑:程序博客网 时间:2024/06/04 20:14
/*translation: 给出n个字符串,求一个最小长度的串,该串包含给出的所有字符串。注意该字符串在长度最小的同时还必须是字典序最小。solution: 状态压缩dp 注意到n的值比较小,所以考虑可以状态压缩。定义dp[i][s]:=在所有字符串选取情况为s的情况下,最前面的字符串为i号字符串 的最小长度。依次枚举下一个字符串可得状态转移方程 dp[i][s | 1 << i] = min(dp[i][s | 1<< i], dp[j][s] + cost[i][j]); cost数组是j字符串前面接上i字符串所加上的最小长度。这个可以通过预处理得到。dp完毕后即可通过搜索来逐渐往后加字符串, 最终得到答案。note: # 一开始打算dp[i][s]来表示最后一个字符串是i,但是考虑到这样求最小的字典序不好求。所以将状态定义成最前面一个是i就很容易 得出。 # 注意如果给出的字符串i包含j,那么j字符串是需要去掉的。date: 2017.1.27(祝自己除夕快乐么么哒)*/#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <algorithm>using namespace std;const int maxn = 17;const int INF = 0x3f3f3f3f;int n, dp[maxn][1 << maxn];string str[maxn], ans;int cost[maxn][maxn]; //cost[i][j]表示将j字符串void init(){for(int i = 0; i < n; i++) {for(int j = 0; j < n; j++) {if(i != j && str[i].find(str[j]) != string::npos) {str[j] = str[i];//如果str[i]包含了str[j]}}}stable_sort(str, str + n);n = unique(str, str + n) - str;memset(cost, 0, sizeof(cost));for(int i = 0; i < n; i++) { for(int j = 0; j < n; j++) if(i != j) { //j的前面接上i int len = min(str[i].length(), str[j].length()); for(int k = 0; k <= len; k++) { if(str[i].substr(str[i].length() - k) == str[j].substr(0, k)) { cost[i][j] = str[i].length() - k; } } }}}void dfs(int id, int s){if(s == 0) return;string tmp; int next_id = -1;for(int i = 0; i < n; i++) if(i != id && (s >> i & 1)) { if(dp[id][s] == dp[i][s & ~(1 << id)] + cost[id][i]) { string t = str[i].substr(str[id].length() - cost[id][i], str[i].length()); if(next_id == -1 || t < tmp) { tmp = t; next_id = i; } }}ans += tmp;dfs(next_id, s & ~(1 << id));}int main(){//freopen("in.txt", "r", stdin);int T, kase = 0;cin >> T; while(T--) {cin >> n;for(int i = 0; i < n; i++)cin >> str[i];if(n > 1) {init();for(int i = 0; i <= n; i++)fill(dp[i], dp[i] + (1 << n), INF);for(int i = 0; i < n; i++) {dp[i][1 << i] = str[i].length();}for(int s = 0; s < 1 << n; s++) { for(int j = 0; j < n; j++) if(dp[j][s] != INF && (s >> j & 1)) { for(int i = 0; i < n; i++) if(!(s >> i & 1)) { dp[i][s | 1 << i] = min(dp[i][s | 1<< i], dp[j][s] + cost[i][j]); } }}int id = 0;for(int i = 1; i < n; i++) { if(dp[i][(1 << n) - 1] < dp[id][(1 << n) - 1]) { id = i; }}ans = str[id];dfs(id, (1 << n) - 1);} else {ans = str[0];}cout << "Scenario #" << ++kase << ":" << endl;cout << ans << endl; cout << endl; } return 0;}
0 0
- poj1795(状态压缩dp,字符串压缩求最小字典序)
- 【POJ1795】DNA Laboratory(状态压缩DP)
- light oj 1073 状态压缩dp+输出字典序最小的解
- 最小汉密尔顿回路问题 状态压缩dp
- hdu 4336 dp求期望(状态压缩)
- hdu1565(状态压缩dp)
- 状态压缩DP(二)
- 状态压缩dp(hdu3406)
- poj2411(状态压缩dp)
- poj1185(状态压缩dp)
- poj3311(状态压缩dp)
- poj3254(状态压缩dp)
- poj2288(状态压缩dp)
- hdu5045(状态压缩dp)
- nefu1109(状态压缩dp)
- hdu5045(压缩状态DP)
- hdu3001(状态压缩dp)
- bzoj1087(状态压缩dp)
- SuperSocket入门(三)-Telnet多服务实例和服务实例交互配置详解_0
- 数值分析 第七章 常微分方程的数值解法
- 1082. Read Number in Chinese (25) PAT甲级
- [RTL综合]综合时保持RTL中直接写入的cell的层级
- scp简单使用
- poj1795(状态压缩dp,字符串压缩求最小字典序)
- NYOJ599 - 奋斗的小蜗牛
- Leetcode 345. Reverse Vowels of a String
- Leetcode 43. Multiply Strings
- 模拟栈的出入 HDOJ 1022 Train Problem I
- Spring 的aop实现原理
- PLSQL游标的使用
- Educational Codeforces Round 17 A+B
- SuperSocket入门(五)-常用协议实现模版及FixedSizeReceiveFilter示例_0