您的位置:首页 > 其它

uva 1204 Fun Game 有趣的游戏 字符串集合的动态规划

2016-02-15 14:14 429 查看
不得不说,此题很难,不得不说,我很渣,看了题解,自己写代码,不但写了一大堆,后来WRONG ANSWER还找不到错了。

只好看紫书的代码。。。

发现好多实用的函数的写法

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: