ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

P1278 单词游戏

2021-09-03 16:34:38  阅读:155  来源: 互联网

标签:20 游戏 int 状压 单词 P1278 dp


P1278 单词游戏

一道比较基础的状压题,看到题解很多人都打的记搜,小蒟蒻来发个状压dp。

由于不能多次使用同一个单词,对于每个单词只有0(不选)1(选)两种情况,并且n只有16显然是状压了。

预处理

对于每个单词我们只关心首尾和长度,所以就记下每个单词的首尾和长度。

设计状态

这题最简单的点就是状态很好设:f[i][j] i为二进制串表示用了哪些单词(基本的状压操作)j表示末尾是哪个单词。

转移

j,k为两单词,当t[j]与h[k]相同时,f[i|(1<<(k-1))][k]=max(f[i][j]+l[k],f[i|(1<<(k-1))][k]);

细节

注意j一定是i状态中选了的词,k是没选过的,以及亿些位运算的细节比如卡了小蒟蒻1h的i|1<<(k-1)才是将i的从右往左第k位变成1。

AC代码

#include<bits/stdc++.h>
#define ll long long 
using namespace std;
int h[20],t[20],l[20],f[200000][20],n,ans;
string s[20];
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>s[i];
        l[i]=s[i].size();
        h[i]=int(s[i][0]);
        t[i]=int(s[i][l[i]-1]);
        f[(1<<(i-1))][i]=l[i];
    }
    for(int i=1;i<=(1<<n)-1;i++)///枚举状态 
    {
        for(int j=1;j<=n;j++)///枚举最后一个词 
        {
            if(!i&(1<<(j-1))||!f[i][j])continue;///细节 
            for(int k=1;k<=n;k++)///枚举加进来的词 
            {
                if(i&(1<<(k-1))||t[j]!=h[k])continue;///细节 
                f[i|(1<<(k-1))][k]=max(f[i][j]+l[k],f[i|(1<<(k-1))][k]);
            }
        }
    }
    for(int i=1;i<=(1<<n)-1;i++)
        for(int j=1;j<=n;j++)
            ans=max(ans,f[i][j]);
    cout<<ans; 
    return 0;
} 

 

虽然dp的效率比不过各种玄学优化的搜索,但dp还是很稳定的。

 

标签:20,游戏,int,状压,单词,P1278,dp
来源: https://www.cnblogs.com/29taorz/p/15223663.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有