P1278 单词游戏【题解】(状压dp)
单词游戏
题目描述
Io和Ao在玩一个单词游戏。
他们轮流说出一个仅包含元音字母的单词,并且后一个单词的第一个字母必须与前一个单词的最后一个字母一致。
游戏可以从任何一个单词开始。
任何单词禁止说两遍,游戏中只能使用给定词典中含有的单词。
游戏的复杂度定义为游戏中所使用的单词长度总和。
编写程序,求出使用一本给定的词典来玩这个游戏所能达到的游戏最大可能复杂度。
输入格式
输入文件的第一行,表示一个自然数N(1≤N≤16),N表示一本字典中包含的单词数量以下的每一行包含字典中的一个单词,每一个单词是由字母A、E、I、O和U组成的一个字符串,每个单词的长度将小于等于100,所有的单词是不一样的。
输出格式
输出文件仅有一行,表示该游戏的最大可能复杂度。
样例 #1
样例输入 #1
5
IOO
IUUO
AI
OIOOI
AOOI
样例输出 #1
16
分析
- 首先看到这个N(1≤N≤16),马上就反应过来了
- 搜索或状压dp
- 由于本蒟蒻刚开始学习状压dp,这篇博客讲的就是状压dp
正文~~
状压dp是啥
“状压DP 又叫集合动态规划。是以结合信息为状态的特殊的动态规划的问题。主要有传统集合动态规划和基于连通性状态压缩的动态规划两种。” ————百度
是不是感觉很高大尚?(我也觉得 )
他非常简(妙 )单(啊 )
状压dp的样子
- 我们回到题目:我们把每个单词看成每一个点,被选了标记成一,他就变成了这样一个样子

- 我们回到题目:我们把每个单词看成每一个点,被选了标记成一,他就变成了这样一个样子
怎么转移?
前置知识
- (<<):左移
- 在十进制上是乘法
- 在二进制上是把整体往左挪一位,例如:100 << 1 = 1000
- (>>): 右移,和左移原理一样,把整体往右移一位
- 对于每个状态,我们枚举这个点有没有选到:如100010这个状态没有选第三个点
- 怎么写代码?
- 这就要用到左移 和 与运算了
- 如果我想要表示一个100,表示第三个状态已被选怎么办?
- 很容易发现
100
=
1
<
<
(
3
−
1
)
100=1<<(3-1)
100=1<<(3−1)
- 于是我们可以总结:
想
要
表
示
第
i
个
点
被
选
=
1
<
<
(
i
−
1
)
想要表示第i个点被选=1<<(i-1)
想要表示第i个点被选=1<<(i−1)
- 于是我们就可以用 i & 1<<(j-1)(i表示当前状态,j表示当前枚举到的点)来表示i状态有没有选点j
考虑转移?
- 枚举每个状态,再枚举这个状态选了那些点,再由这些点进行转移
- 什么意思?
- 例如状态10001,这个状态包含1,5这2个点
- 如果点2可以接到点1后面
- 那么
f
[
11001
]
=
m
a
x
(
f
[
10001
]
+
v
,
f
[
11001
]
)
f[11001]=max(f[10001]+v,f[11001])
f[11001]=max(f[10001]+v,f[11001])
- 然后输出
f
[
(
1
<
<
n
)
−
1
]
f[(1<<n)-1]
f[(1<<n)−1]全部点被选即可
针对这一道题?
- 我们刚刚那一串分析有一个重要的
B
U
G
BUG
BUG!
- 那就是其他点怎么转到这个点?
- 其实我们只要将
f
f
f数组增加一维用来表示这个状态最后的字母是什么即可
- 我们刚刚那一串分析有一个重要的
C
o
d
e
:
Code:
Code:
#include<bits/stdc++.h>
using namespace std;
int n,dp[30][1<<16];
string a[20];
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<=n;i++)
dp[a[i][int(a[i].size()-1)]-'A'][1<<(i-1)]=int(a[i].size());//初始化
for(int i=1;i<=1<<n;i++){
for(int j=1;j<=n;j++){//考虑用j进行转移
if(!(i&1<<(j-1))) continue;//如果这个状态不包括这个点,就跳过
for(int k=1;k<=n;k++){
if(i&1<<(k-1)) continue;//如果状态选了k这个点,那么就不必要再选了
if(a[j][int(a[j].size())-1]-'A'!=a[k][0]-'A') continue;//如果接不上,也跳过
dp[a[k][int(a[k].size())-1]-'A'][i|(1<<(k-1))]=max(dp[a[j][int(a[j].size())-1]-'A'][i]+int(a[k].size()),dp[a[k][int(a[k].size())-1]-'A'][i|(1<<(k-1))]);
}
}
}
int maxx=0;
for(int i=1;i<=1<<n;i++){
for(int j=1;j<=n;j++){
maxx=max(maxx,dp[a[j][int(a[j].size())-1]-'A'][i]);
}
}
cout<<maxx;//由于不一定全选,所以枚举每个状态,输出即可
return 0;
}
推荐另外一道很相像的题:
吃奶酪
打代码去咯!
P1278 单词游戏【题解】(状压dp)的更多相关文章
- 洛谷 P1278 单词游戏 【状压dp】
题目描述 Io和Ao在玩一个单词游戏. 他们轮流说出一个仅包含元音字母的单词,并且后一个单词的第一个字母必须与前一个单词的最后一个字母一致. 游戏可以从任何一个单词开始. 任何单词禁止说两遍,游戏中只 ...
- O - Matching 题解(状压dp)
题目链接 题目大意 给你一个方形矩阵mp,边长为n(n<=21) 有n个男生和女生,如果\(mp[i][j]=1\) 代表第i个男生可以和第j个女生配对 问有多少种两两配对的方式,使得所有男生和 ...
- [BZOJ 1879][SDOI 2009]Bill的挑战 题解(状压DP)
[BZOJ 1879][SDOI 2009]Bill的挑战 Description Solution 1.考虑状压的方式. 方案1:如果我们把每一个字符串压起来,用一个布尔数组表示与每一个字母的匹配关 ...
- NOIP2017 宝藏 题解报告【状压dp】
题目描述 参与考古挖掘的小明得到了一份藏宝图,藏宝图上标出了 n 个深埋在地下的宝藏屋, 也给出了这 n 个宝藏屋之间可供开发的 m 条道路和它们的长度. 小明决心亲自前往挖掘所有宝藏屋中的宝藏.但是 ...
- TZOJ 2289 Help Bob(状压DP)
描述 Bob loves Pizza but is always out of money. One day he reads in the newspapers that his favorite ...
- 【bzoj5161】最长上升子序列 状压dp+打表
题目描述 现在有一个长度为n的随机排列,求它的最长上升子序列长度的期望. 为了避免精度误差,你只需要输出答案模998244353的余数. 输入 输入只包含一个正整数n.N<=28 输出 输出只包 ...
- TZOJ 4912 炮兵阵地(状压dp)
描述 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示),也可能是平原(用"P" ...
- POJ 1684 Corn Fields(状压dp)
描述 Farmer John has purchased a lush new rectangular pasture composed of M by N (1 ≤ M ≤ 12; 1 ≤ N ≤ ...
- 【uoj#37/bzoj3812】[清华集训2014]主旋律 状压dp+容斥原理
题目描述 求一张有向图的强连通生成子图的数目对 $10^9+7$ 取模的结果. 题解 状压dp+容斥原理 设 $f[i]$ 表示点集 $i$ 强连通生成子图的数目,容易想到使用总方案数 $2^{sum ...
- Codeforces Beta Round #8 C. Looking for Order 状压dp
题目链接: http://codeforces.com/problemset/problem/8/C C. Looking for Order time limit per test:4 second ...
随机推荐
- 驱动开发:内核LDE64引擎计算汇编长度
本章开始LyShark将介绍如何在内核中实现InlineHook挂钩这门技术,内核挂钩的第一步需要实现一个动态计算汇编指令长度的功能,该功能可以使用LDE64这个反汇编引擎,该引擎小巧简单可以直接在驱 ...
- vue3 页面跳转
需要引入 useRouter import {useRouter} from "vue-router"; 然后声明对象 代码如下 export default { setup() ...
- 将自己的组件打包发布到npm
在项目中有些组件在各个项目中都会调用,那么将组件发布到npm ,用到的项目去下载,这样会省去一些不必要的麻烦. 将组件发布到npm 中的步骤 做个记录 1.项目的创建,我这里使用 vue init w ...
- 支持JDK19虚拟线程的web框架之四:看源码,了解quarkus如何支持虚拟线程
欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 前文链接 支持JDK19虚拟线程的web框架,之一:体 ...
- Go语言核心36讲31
我们在前两篇文章中讨论了互斥锁.读写锁以及基于它们的条件变量,先来总结一下. 互斥锁是一个很有用的同步工具,它可以保证每一时刻进入临界区的goroutine只有一个.读写锁对共享资源的写操作和读操作则 ...
- hashcat 命令
hashcat --force --stdout -a 6 tmp.txt ?d?d?d?d?d?d?d > result.txt tips:将tmp.txt字典中的内容与7位随机掩码字符组合, ...
- 关于python转义字符在正则匹配中的问题研究
问题 首先看一个问题: import re text = r"\学" print(text) zz = r"\学" result = re.findall(zz ...
- 解决Linux使用deepin-wine跑qq,tim打不开文件所在文件夹
前言 使用deepin-wine 跑qq,发现一个小bug 这里点击打开文件夹是没有效果的,包括在 tim 上也是这样 问题原因 出现这个问题是因为 deepin-wine 跑的 QQ,Tim 打开文 ...
- 腾讯云数据库SaaS致力于构建数据库分布式云,为更多更广的用户提供服务
大数据时代,数据库 SaaS 是企业实现降本增效和业务创新的重要抓手.在腾讯全球数字生态大会数据库 SaaS 专场上,腾讯云发布了多项数据库 SaaS 产品能力升级,并重点分享了其在上云.日常运维.数 ...
- Tkinter根据屏幕分辨率最大化适应屏幕
还不能够实现所有组件随分辨率自动变化 # 实现的是界面覆盖整个屏幕 from tkinter import * import win32api, win32con # 获取屏幕的分辨率 width = ...