您的位置:首页 > 产品设计 > UI/UE

codeforces 83E Two Subsequences (状态dp,难)

2015-02-21 16:00 225 查看
题意:

给出一些串,现在要将这些串分成两个部分,每部分的要将这部分的串进行合并,合并就是将公共前后缀去掉变成一个串(每次操作两个串知道全部变成一个串为止,当让长度要尽量小)。问如何划分使得两个集合各自合并后加起来的长度最小。

题解:

网上的题解虽然看懂了但是还是不懂得如何操作。查了下cf大牛ac的代码,做法是这样:dp[i][s]长度为i状态为s的串的某个部位,因为每个串最多20长度可以状压。不是很懂,具体看看代码,有待深入理解。

#include<iostream>
#include<math.h>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
#include<map>
#include<set>
using namespace std;
#define B(x) (1<<(x))
typedef long long ll;
const int oo=0x3f3f3f3f;
const ll OO=1LL<<61;
const ll MOD=10007;
const int maxn=200000+5;
int dp[21][1<<20];
int a[maxn];
char str[25];

void cmin(int &a,int b)
{
    if(b<a) a=b;
}

int main()
{
    int n,m;
    while(scanf("%d",&n)!=EOF)
    {
        memset(a,0,sizeof a);
        memset(dp,0x3f,sizeof dp);
        for(int i=1;i<=n;i++)
        {
            scanf("%s",str);m=strlen(str);
            for(int j=0;j<m;j++) a[i]=(a[i]<<1)|(str[j]-'0');
        }
        dp[0][0]=0;
        int ans=m;
        for(int i=2,j;i<=n;i++)
        {
            for(j=m;(a[i-1]&((1<<j)-1))!=(a[i]>>m-j)&&j;j--);
            ans+=m-j;
            int k=oo;
            for(int p=0;p<=m;p++) cmin(k,dp[p][a[i]>>m-p]-p+j);
            for(int p=0;p<=m;p++) cmin(dp[p][a[i-1]&((1<<p)-1)],k);
        }
        int t=0;
        for(int i=0;i<=m;i++)
            for(int j=0;j<(1<<i);j++)
                cmin(t,dp[i][j]);
        printf("%d\n",ans+t);
    }
    return 0;
}
/***
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: