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 ...
随机推荐
- Aspose.Words 操作 Word 画 EChart 图
使用 Aspose.Words 插件在 Word 画 EChart 图 使用此插件可以画出丰富的 EChart 图,API 参考 https://reference.aspose.com/words/ ...
- 【JavaWeb】学习笔记——JSP
概念 全称:Java Server Pages, Java服务端页面 描述:一种动态的网页技术,可以在其中定义HTML.JS.CSS等静态内容,以及Java代码的动态内容 说明:JSP = HTML ...
- SpringBoot自定义注解+异步+观察者模式实现业务日志保存
一.前言 我们在企业级的开发中,必不可少的是对日志的记录,实现有很多种方式,常见的就是基于AOP+注解进行保存,但是考虑到程序的流畅和效率,我们可以使用异步进行保存,小编最近在spring和sprin ...
- Vue中常用的几种传值方式
Vue中常用的几种传值方式 1. 父传子 父传子的实现方式就是通过props属性,子组件通过props属性接收从父组件传过来的值,而父组件传值的时候使用 v-bind 将子组件中预留的变量名绑定为da ...
- uni-app 配置MuMu手机模拟器 (2022-2-24)
(1)到官网"https://mumu.163.com/"下载,我选中的中间的那个 (2)下载完成后,默认安装即可,直接等待安装完成 (3)在uni-app里设置端口,在uni-a ...
- linux-web基础
web基础 [TOC] 网上冲浪 网上冲浪:在Internet互联网上获取各种信息,进行工作.娱乐,在英文中上网是" surfing the internet",因"su ...
- jquery datatable 粗犷
需要学习: HTML.CSS.Javascript Bootstrap: 基于以上三个的一个框架 jQuery:一个 JavaScript 库. jQuery 极大地简化了 JavaScript 编程 ...
- 【jmeter】将“察看结果树”中的数据保存到本地
操作说明: 1. "察看结果树"页面,[配置]导出项: 2. "察看结果树"页面,[文件名]选框输入导出文件及路径: 3. 点击jmeter[启动]按钮,响应 ...
- 定制ASP.NET Core的身份认证
大家好,我是张飞洪,感谢您的阅读,我会不定期和你分享学习心得,希望我的文章能成为你成长路上的垫脚石,让我们一起精进. 在本章,我们将学习如何定制ASP.NET Core认证机制.微软把安全认证当做AS ...
- AR路由器如何配置Portal认证(二层网络)
规格 适用于所有版本.所有形态的AR路由器. 说明: 4GE-2S.4ES2G-S.4ES2GP-S和9ES2单板不支持NAC功能. 组网需求 如图所示,某公司接待室需要部署一套身份认证系统,对接入网 ...