UVA1204 fun game 【状压DP】

来源:互联网 发布:北明软件待遇 编辑:程序博客网 时间:2024/05/17 08:15

题目文档

题意:一群小孩(至少两个)围成一圈做游戏。每一轮从某个小孩开始往他左边或者右边传手帕。一个小孩拿到手帕后在手帕上写上自己的性别,男孩写B,女孩写G,然后按照相同的方向传递给下一个小孩,每一轮都可能在任何一个小孩写完后停止,现在游戏已经进行了n轮,已知n轮中每轮手帕上留下的字,问最少可能有几个小孩


分析:见紫书P294-P295(没有题解,个人笔记)

#include<cstring>#include<iostream>#include<cstdio>#include<algorithm>#include<string>using namespace std;struct edge{    string s,rev;    bool operator<(const edge &c)    {        return s.length()<c.s.length();    }}a[22];string s[22][2];int len[22],n;int fugai(const string &a,const string &b)   //最大能覆盖长度,注意是能覆盖,不是重复{    int la=a.length(),lb=b.length();    for(int l=1;l<la;l++)    {        int i=l,j=0;        while(a[i]==b[j]&&i<la&&j<lb)        {            i++;j++;        }        if(i==la)return j;    }    return 0;}void update(int &v,int c){    if(v<0||v>c)v=c;}int dp[(1<<16)+10][18][2],g[18][18][2][2];void solve(){   int c=(1<<n)-1;   memset(dp,-1,sizeof(dp));   dp[1][0][0]=len[0];   for(int s=1;s<c;s++)   {       for(int i=0;i<n;i++)       {           for(int ii=0;ii<2;ii++)           {               if(dp[s][i][ii]==-1)continue;               for(int j=1;j<n;j++)               {                   if(s&(1<<j))continue;                   for(int jj=0;jj<2;jj++)                   {                       update(dp[s|(1<<j)][j][jj],dp[s][i][ii]+len[j]-g[i][j][ii][jj]);                   }               }           }       }   }   int mixx=-1;   for(int i=0;i<n;i++)   {       for(int ii=0;ii<2;ii++)       {   if(dp[c][i][ii]==-1)continue;           dp[c][i][ii]-=g[i][0][ii][0];           update(mixx,dp[c][i][ii]);       }   }   if(mixx<=1)    mixx=2;   cout<<mixx<<endl;   return ;}int main(){    while(scanf("%d",&n)!=EOF&&n)    {        for(int i=1;i<=n;i++)        {            cin>>a[i].s;            a[i].rev=a[i].s;            reverse(a[i].rev.begin(),a[i].rev.end());        }        sort(a+1,a+n+1);        int n2=0;        for(int i=1;i<=n;i++)//消灭串中串        {            bool ok=true;            for(int j=i+1;j<=n;j++)            {                if(a[j].s.find(a[i].s)!=string::npos||                   a[j].s.find(a[i].rev)!=string::npos)                {                    ok=false;                    break;                    //cout<<" ******";                }            }            if(ok)            {               // cout<<a[i].s<<endl;                s[n2][0]=a[i].s;                s[n2][1]=a[i].rev;                len[n2]=a[i].s.length();                n2++;            }        }        n=n2;        for(int i=0;i<n;i++)        {            for(int j=0;j<n;j++)            {                for(int ii=0;ii<2;ii++)                {                    for(int jj=0;jj<2;jj++)                    {                        g[i][j][ii][jj]=fugai(s[i][ii],s[j][jj]);                    }                }            }        }        solve();    }    return 0;}