uva 1204 Fun Game 有趣的游戏 字符串集合的动态规划
2016-02-15 14:14
429 查看
不得不说,此题很难,不得不说,我很渣,看了题解,自己写代码,不但写了一大堆,后来WRONG ANSWER还找不到错了。
只好看紫书的代码。。。
发现好多实用的函数的写法
代码这个东西,写的越长,错误的几率就越大。
回顾:
思路:先考虑一排+不能翻转(定了传递顺序)的情形,从简单情形入手
简化与初步分析:剔除完全能被其它字符串包含的字符串
解法:分阶段的动归
集合表示哪些字符串已经取了。加上一维表示最后一个字符串是谁。神奇,分阶段+集合
这里的集合用的相当好,我不用知道字符串时怎样排列的,只用知道用了哪些字符串,最后排的字符串是谁,然后最优值是多少。
约制(有益无害):1.从左往右安排字符串。
2.第一个放的字符串必须是编号为0(如果编号从1开始,则放1)的字符串
学着写了份代码:
只好看紫书的代码。。。
发现好多实用的函数的写法
reverse(tmps[i].rev.begin(),tmps[i].rev.end()); if(tmps[j].s.find(tmps[i].s)!=string::npos || tmps[j].s.find(tmps[i].rev)!=string::npos) bool operator<(const Node y)const { return s.length()<y.s.length(); } int cal_same( string &a,string & b) inline void update(int& x, int v) { if(x < 0 || v < x) x = v; }
代码这个东西,写的越长,错误的几率就越大。
回顾:
思路:先考虑一排+不能翻转(定了传递顺序)的情形,从简单情形入手
简化与初步分析:剔除完全能被其它字符串包含的字符串
解法:分阶段的动归
集合表示哪些字符串已经取了。加上一维表示最后一个字符串是谁。神奇,分阶段+集合
这里的集合用的相当好,我不用知道字符串时怎样排列的,只用知道用了哪些字符串,最后排的字符串是谁,然后最优值是多少。
约制(有益无害):1.从左往右安排字符串。
2.第一个放的字符串必须是编号为0(如果编号从1开始,则放1)的字符串
学着写了份代码:
/**========================================== * This is a solution for ACM/ICPC problem * * @source:uva 1204 * @type: * @author: wust_ysk * @blog: http://blog.csdn.net/yskyskyer123 * @email: 2530094312@qq.com *===========================================*/ #include<cstdio> #include<string> #include<cstring> #include<iostream> #include<cmath> #include<algorithm> #define ysk(x) (1<<(x)) #define REP(i,n) for(int i = 0; i < (n); i++) using namespace std; typedef long long ll; const int INF =0x3f3f3f3f; const int maxn=16 ; //const int maxV=12 ; int n,tot; int same[maxn+3][maxn+3][2][2]; struct Node { string s,rev; bool operator<(const Node y)const { return s.length()<y.s.length(); } }tmps[maxn+3]; string s[maxn+3][2]; int cal_same( string &a,string & b) { int len1=a.length(); int len2=b.length(); for(int st=1;st<len1;st++) { if(st+len2-1<=len1-1) continue; bool ok=true; int tmp=0; for(int j=0;st+j<len1;j++) { if(a[st+j]!=b[j]) {ok=false;break;} tmp++; } if(ok) return tmp; } return 0; } void init() { sort(tmps,tmps+n); int cnt=0; tot=0; REP(i,n) { bool need=true; for(int j=i+1;j<n;j++) { if(tmps[j].s.find(tmps[i].s)!=string::npos || tmps[j].s.find(tmps[i].rev)!=string::npos) { need=false; break; } } if(need) { s[cnt][0]=tmps[i].s; s[cnt++][1]=tmps[i].rev; tot+=tmps[i].s.length(); } } n=cnt; REP(i,n) REP(j,n) REP(x,2) REP(y,2) { same[i][j][x][y]=cal_same(s[i][x],s[j][y]); } } int full,dp[ysk(maxn)+3][maxn+3][2]; void update(int &x ,int v) { if(x<v) x=v; } void work() { full=ysk(n)-1; memset(dp,-1,sizeof dp); dp[1][0][0]=0; for(int st=2;st<=full;st++) { for(int add=0;add<n;add++) if(st&ysk(add)) { int v=st^ysk(add); for(int ed=0;ed<n;ed++) if(v&ysk(ed)) { REP(x,2) { if(dp[v][ed][x]<0) continue; REP(y,2) { update(dp[st][add][y],dp[v][ed][x]+same[ed][add][x][y] ); } } } } } int ans=-1; REP(i,n) REP(x,2) { if(dp[full][i][x]<0) continue; update(ans,dp[full][i][x]+same[i][0][x][0]); } ans=max(2,tot-ans); printf("%d\n",ans); } int main() { while(cin>>n&&n) { REP(i,n) { cin>>tmps[i].s; tmps[i].rev=tmps[i].s; reverse(tmps[i].rev.begin(),tmps[i].rev.end()); } init(); work(); } return 0; }
相关文章推荐
- TinyOS视频第二集内容介绍
- Problem1(Multiples of 3 and 5)
- IOS开发证书显示“此证书的签发者无效”解决方法
- IOS开发证书显示“此证书的签发者无效”解决方法
- 《SSH客户端实现和Linux(Centos)共享文件以及批量管理》
- 对于javascript中Null和Undefined类型的区分
- C#实现自己的Ctr+V
- lldb调试命令
- mysql 错误集锦
- RP2836 OUT0-OUT7 对应关系
- zookeeper入门与实战
- IOS开发证书变成“此证书的签发者无效”解决方法
- spring的事务控制
- python 生成随机密码
- “爱心接力 温暖传递” ——利尔达走进福利院,冬日送温暖活动
- iOS App名称和内容国际化
- thinkPhp 框架学习——架构
- [LeetCode] Number of Islands II 岛屿的数量之二
- 正则表达式基本语法
- zookeeper自己的理解