状态压缩DP poj 2817 WordStack 入门题

题目链接:  http://poj.org/problem?id=2817

题意: 给出n个字符串,一个排列使得相邻字符串之间的共同字母总数最多,这里的字母必须是一一对应的;

可以加空格。比如abc 和 asc,可以有很多种组合方式;如:

abc      abc        abc          _abc   __abc         ___abc

asc       _ asc   __ asc     asc     asc              asc

真心觉英语水平弱爆了,理解错了若干次。开始我以为是lcs,错。改,我又弱弱的以为要保持队形。大哭


分析: 直接预处理出串之间的共同字母的最大数,然后就是简单的状态压缩dp

dp[news][j] = max(dp[news][j], dp[s][i] + dist[i][j] );

dp[s][i] 表示经过s里的所有点,并以i为结束点;

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
using namespace std;

template<class T>
void max( T &a, T b ) { if(a < b) a = b; }

const int maxn = 11;
int n;
int dist[maxn][maxn];
int dp[1<<maxn][maxn];
char str[maxn][maxn];

int count( int x, int y ) {
    int ans = 0;
    int len_x = strlen(str[x]);
    int len_y = strlen(str[y]);
    for ( int i=0; i<10; ++i ) {
        int cnt = 0;
        for ( int j=0; j+i<len_y && j<len_x; ++j )
          if(str[x][j] == str[y][j+i] ) ++cnt;
        max(ans, cnt);

        cnt = 0;
        for ( int j=0; j+i<len_x && j<len_y; ++j )
           if(str[x][j+i] == str[y][j] ) ++cnt;
        max(ans, cnt);
    }
    return ans;
};

int main( ) {
    while( scanf("%d", &n), n>0 )
    {
        for ( int i=0; i<n; ++i )
          scanf ("%s", str[i]);
        for ( int i=0; i<n; ++i )
          for ( int j=i+1; j<n; ++j )
            dist[i][j] = dist[j][i] = count(i, j);
        memset (dp, 0, sizeof dp);

        int full = 1<<n, ans = 0;
        for ( int s=1; s<full; ++s ) {
            for ( int i=0; i<n; ++i ) if(s&(1<<i) )
            {
                for ( int j=0; j<n; ++j ) if(!(s&(1<<j))){
                     int news = s^(1<<j);
                     max(dp[news][j], dp[s][i]+ dist[i][j]  );
                     max(ans, dp[news][j]);
                }
            }
        }
        printf ("%d\n", ans);
    }
};
0ms无压力,复杂度0((1<<n)*n*n)。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值