hdu3828动态规划
来源:互联网 发布:pp助手 mac打不开 编辑:程序博客网 时间:2024/05/25 05:35
题目描述:
题意就不讲了,最终的模型是:给你n个长度64的串,让你找一个最短的串str,让这个n个串都是str的子串,如果长度相同,取字典序最小的。
解题报告:
首先,预处理,share[i][j]表示第i个字符串的尾部和第j个字符串的头部的公共长度,如果j是i的子串,直接删除j。
我们从右往左构造字符串(应为比较字典序是从往右的,所以当有答案冲突时,只需要比较最左端的字符串即可得到字典序最小的答案)。
dp[i][j]表示当前在i状态时,用j串作为最左端的串时的最小长度。
i是一个15位二进制数字,哪一位为1表示那一位对应的字符串已经使用过了。
那么,从dp[i][j]开始,一次扫描n个串:
对于串k,如果(i>>k&1) == 0,表示还没用过k,那么可以转移到dp[(i | (1 << k))][k]
转移后的最小长度为:dp[i][j] + len[k] - share[k][j];(减去公共的部分)
这样,每个dp[i][j]都维持一个最小的数字,最后扫描dp[1 << n - 1][x]中的最小值即可。
对于冲突,要维护一个pre[i][j],表示dp[i][j]是由哪个状态转化过来的。如果在dp[i][j],冲突,由于是从右往左拼接,那么只需比较冲突的两个串的最头的两个的字典序(比较绕,应该能明白)。
#include <iostream>#include <cstdio>#include <vector>#include <cstring>#include <algorithm>#define NN 66000#define N 25#define inf (1 << 30)#define mod 1000000009using namespace std;int n;int fail[100], able[20], len[20];int share[20][20], dp[85536][20], pre[85536][20][2];long long a[20];char str[20][100], cat[20][20][200], tmp[100], ans_s[1100];vector<int> q;/*==================================================*\| KMP匹配算法O(M+N)| CALL: res=kmp(str, pat); 原串为str; 模式为pat(长为P);\*==================================================*/int kmp(char* str, char* pat){ int i, j, k; memset(fail, -1, sizeof(fail)); for (i = 1; pat[i]; ++i) { for (k = fail[i-1]; k >= 0 && pat[i] != pat[k + 1]; k = fail[k]); if (pat[k + 1] == pat[i]) fail[i] = k + 1; } i = j = 0; while( str[i] && pat[j] ) // By Fandywang { if( pat[j] == str[i] ) ++i, ++j; else if (j == 0) ++i;//第一个字符匹配失败,从str下个字符开始 else j = fail[j - 1] + 1; } if (pat[j]) return j; else return -1;}int init(){ int i, j, size, e; long long temp; for (i = 1; i <= n; i++) { temp = a[i]; size = 0; while (temp != 0) { if (temp % 2) tmp[size++] = '1'; else tmp[size++] = '0'; temp /= 2; } for (j = 0; j < size; j++) str[i][j] = tmp[size - 1 - j]; str[i][size] = 0; } fill(able + 1, able + n + 1, 1); for (i = 1; i <= n; i++) for (j = 1; j <= n; j++) { if (j == i || able[j] == 0) continue; if (kmp(str[j], str[i]) == -1) able[i] = 0; } e = 0; for (i = 1; i <= n; i++) if (able[i]) strcpy(str[++e], str[i]); n = e; for (i = 1; i <= n; i++) for (j = 1; j <= n; j++) { len[i] = strlen(str[i]); share[i][j] = kmp(str[i], str[j]); } for (i = 1; i <= n; i++) for (j = 1; j <= n; j++) { if (j == i) continue; strcpy(cat[i][j], str[i]); strcat(cat[i][j], str[j] + share[i][j]); } memset(dp, -1, sizeof(dp)); memset(pre, -1, sizeof(pre)); for (i = 1; i <= n; i++) { dp[1 << (i - 1)][i] = len[i]; pre[1 << (i - 1)][i][0] = -1; } return 1;}int get_ans(int k, int id, int from){ if (from == -1) strcpy(ans_s, str[id]); else strcat(ans_s, str[id] + share[from][id]); if (pre[k][id][0] != -1 && pre[k][id][1] !=- 1) get_ans(pre[k][id][0], pre[k][id][1], id); return 1;}int get_int(){ int i, size = strlen(ans_s); long long ans = 0, temp = 1; for (i = size - 1; i >= 0; i--) { if (ans_s[i] == '1') { ans += temp; if (ans > mod) ans %= mod; } temp *= 2; if (temp > mod) temp %= mod; } printf("%I64d\n", ans); return 1;}int solve(){ int i, j, k, st, val, id ,maxi; for (i = 1; i < (1 << n); i++) for (j = 1; j <= n; j++) { if (dp[i][j] == -1) continue; for (k = 1; k <= n; k++) { if ((1 << (k - 1)) & i) continue; st = i | (1 << (k - 1)); val = dp[i][j] + len[k] - share[k][j]; if (dp[st][k] == -1 || dp[st][k] > val) { dp[st][k] = val; pre[st][k][0] = i; pre[st][k][1] = j; } else if (dp[st][k] == val) { if (strcmp(cat[k][j], cat[k][pre[st][k][1]]) < 0) pre[st][k][0] = i, pre[st][k][1] = j; } } } k = (1 << n) - 1, id = -1, maxi = inf; for (i = 1; i <= n; i++) { if (dp[k][i] < maxi) maxi = dp[k][i], id = i; else if (dp[k][i] == maxi && strcmp(str[i], str[id]) < 0) id = i; } memset(ans_s, 0, sizeof(ans_s)); get_ans(k, id, -1); get_int(); return 1;}int main(){ int i, j; while (scanf("%d", &n) != EOF) { for (i = 1; i <= n; i++) scanf("%I64d", &a[i]); init(); solve(); } system("pause"); return 0;}
- hdu3828动态规划
- 动态规划!!!动态规划!!!
- 动态规划
- 动态规划
- 动态规划
- 动态规划
- 动态规划
- 动态规划
- 动态规划
- 动态规划
- 动态规划
- 动态规划
- 动态规划
- 动态规划
- 动态规划
- 动态规划
- 动态规划
- 动态规划
- jQuery(1.6.3) 中css方法对浮动的实现缺陷
- MYSQL数据导出和导入
- C6000嵌入汇编C与汇编对照及功能说明
- Spotlight on oracle 使用
- linux生成动态库和静态库
- hdu3828动态规划
- Hibernate中常见问题 No row with the given identifier exists问题的原因及解决
- Hibernate异常No row with the given identifier exists 解决方法
- Plone 4.x 学习之创建自定义工具
- Google谷歌权重09年算法
- 程序江湖:第十九章 四季如春的昆明
- HDU 4006 The kth great number [2011 大连网络赛] [AVL树解法]
- 在一个activity中添加多个listview
- Teamcenter 入门开发系列问答(2)