状压dp的题目列表 (一)
状压dp的典型的例子就是其中某个数值较小。
但是某个数值较小也不一定是状压dp,需要另外区分的一种题目就是用暴力解决的题目,例如UVA818 紫书215
题目列表:
①校长的烦恼 UVA10817 紫书286
②20个问题 UVA 1252 紫书287
③
④
⑤
⑥
⑦
⑧
⑨
⑩
一:校长的烦恼 UVA10817 紫书286
题目大意:n个求职者,m个教师,需要讲授s门课程,每门课要有至少2个人讲授。教师是必须雇佣的,求职者看情况。给出教师和求职者的工资和能教授的科目。问怎么雇佣才能支付最少的工资?
思路:定义dp[i][s1][s2]表示,s1表示每门课只有一个人教,s2表示每门课有两名以上的人教的。i表示前i个人的雇佣情况,这样进行dp就好了。 具体看紫书吧,很详细
//看看会不会爆int! 或者绝对值问题。
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define fi first
#define se second
#define ALL(a) a.begin(), a.end()
const int maxs = ( << ) + ;
const int inf = 0x3f3f3f3f;
const int maxn = + ;
int s, m, n;
int dp[maxn][maxs][maxs], money[maxn], st[maxn]; int dfs(int i, int s1, int s2){
if (i == m + n){
return s2 == (<<s)- ? : inf;
}
int &ans = dp[i][s1][s2];
if (ans >= ) return ans;
ans = inf;
if (i >= m) ans = dfs(i + , s1, s2);
int t = st[i];
int tmp = s1 & t;
ans = min(ans, dfs(i + , s1 | t, s2 | tmp) + money[i]);
return ans;
} int main(){
string line;
int x;
while (getline(cin, line)){
stringstream ss(line);
ss >> s >> m >> n;
if (s == ) break;
for (int i = ; i < m + n; i++){
getline(cin, line);
stringstream ss(line);
ss >> money[i];
st[i] = ;
while (ss >> x) st[i] |= ( << x-);
}
memset(dp, -, sizeof(dp));
dfs(, , );
printf("%d\n", dp[][][]);
}
return ;
}
关键:学会划分情况
二:20个问题 UVA1252 紫书267
题目大意:有n个长度为m的二进制串,每个都是不同的。为了把所有字符串区分开,你可以询问,每次可以问某位上是0还是1。问最少提问次数,可以把所有字符串区分开来。
思路:dp是要枚举已知的所需要的所有状态的,那么我们如何来枚举目前的状态呢。首先我们定义dp[s][a],s表示目前已经询问了的集合,a表示目前s的子集当中的特征集。因此就表示,已经询问了特征集s,确认了所具备的特征集a,还需要询问的最小次数是多少。
因此我们的决策时dp[s][a] = max(dp[s + {k}][a + {k}], dp[s + {k}][a]) + 1;
然后通过dfs来解决就行了。虽然也可以用递推来实现。
//看看会不会爆int! 或者绝对值问题。
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define fi first
#define se second
#define ALL(a) a.begin(), a.end()
///当所有的物品所具备的特征只剩下1的时候,说明其他全都访问过
const int maxn = + ;
const int maxm = ( << ) + ;
int cnt[maxm][maxm], dp[maxm][maxm];
int n, m;
char ch[maxn]; void init(){
memset(cnt, , sizeof(cnt));
for (int i = ; i < n; i++){
scanf("%s", ch);
int t = ;
for (int j = ; j < m; j++)
if (ch[j] == '') t |= ( << j);
for (int j = ; j < ( << m); j++){///给所有的都做上标记,一个的时候,两个的时候都有
cnt[j][j & t]++;
}
}
} int dfs(int s, int a){
if (cnt[s][a] <= ) return ;
if (cnt[s][a] == ) return ; int &ans = dp[s][a];
if (dp[s][a] >= ) return ans;
ans = m;
for (int i = ; i < m; i++){
if (s & ( << i)) continue;
int s2 = s | ( << i), a2 = a | ( << i);
if (cnt[s2][a] >= && cnt[s2][a2] >= ){
int tmp = max(dfs(s2, a), dfs(s2, a2)) + ;
ans = min(tmp, ans);
}
}
return ans;
} int main(){
while (scanf("%d%d", &m, &n) == && n+m > ){
memset(dp, -, sizeof(dp));
init();
printf("%d\n", dfs(, ));
}
return ;
}
感觉这道题让现在我这样的水平的人来做肯定做不来,要仔细看看
三:
四:
五:
六:
七:
八:
九:
十:
状压dp的题目列表 (一)的更多相关文章
- 状压dp(状态压缩&&dp结合)学习笔记(持续更新)
嗯,作为一只蒟蒻,今天再次学习了状压dp(学习借鉴的博客) 但是,依旧懵逼·································· 这篇学习笔记是我个人对于状压dp的理解,如果有什么不对的 ...
- POJ1185 状压dp(二进制//三进制)解法
很显然这是一道状压dp的题目 由于每个最优子结构和前两行有关,一个显而易见的想法是用三维dp[i][j][k]用来记录在第i行下为j状态,i - 1行为k状态时的最大值,然而dp[100][1 < ...
- ZOJ 3777 - Problem Arrangement - [状压DP][第11届浙江省赛B题]
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3777 Time Limit: 2 Seconds Me ...
- M - Little Pony and Harmony Chest 状压dp
M - Little Pony and Harmony Chest 怎么感觉自己越来越傻了,都知道状态的定义了还没有推出转移方程. 首先这个a的范围是0~30 这里可以推出 b数组的范围 0~60 ...
- 「算法笔记」状压 DP
一.关于状压 dp 为了规避不确定性,我们将需要枚举的东西放入状态.当不确定性太多的时候,我们就需要将它们压进较少的维数内. 常见的状态: 天生二进制(开关.选与不选.是否出现--) 爆搜出状态,给它 ...
- 状压DP入门详解+题目推荐
在动态规划的题型中,一般叫什么DP就是怎么DP,状压DP也不例外 所谓状态压缩,一般是通过用01串表示状态,充分利用二进制数的特性,简化计算难度.举个例子,在棋盘上摆放棋子的题目中,我们可以用1表示当 ...
- 状压DP详解+题目
介绍 状压dp其实就是将状态压缩成2进制来保存 其特征就是看起来有点像搜索,每个格子的状态只有1或0 ,是另一类非常典型的动态规划 举个例子:有一个大小为n*n的农田,我们可以在任意处种田,现在来描述 ...
- nefu1109 游戏争霸赛(状压dp)
题目链接:http://acm.nefu.edu.cn/JudgeOnline/problemShow.php?problem_id=1109 //我们校赛的一个题,状压dp,还在的人用1表示,被淘汰 ...
- poj3311 TSP经典状压dp(Traveling Saleman Problem)
题目链接:http://poj.org/problem?id=3311 题意:一个人到一些地方送披萨,要求找到一条路径能够遍历每一个城市后返回出发点,并且路径距离最短.最后输出最短距离即可.注意:每一 ...
随机推荐
- js 邮箱和手机号码验证
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- linux安装oracle远程客户端
文章参考:http://blog.csdn.net/caomiao2006/article/details/11901123 感谢博友分享O(∩_∩)O~ 安装oracle 远程客户端(一般情况下本地 ...
- OBS源码编译开发
本文来自网易云社区 作者:梁敏 OBS简介 OBS(Open Broadcaster Software)是免费开源的视频录制和直播软件,支持运行在windows,Mac和linux平台.官方链接 ht ...
- tomcat 异常
Removing obsolete files from server... Could not clean server of obsolete files: null java.lang.Null ...
- Spark集群管理器介绍
Spark可以运行在各种集群管理器上,并通过集群管理器访问集群中的其他机器.Spark主要有三种集群管理器,如果只是想让spark运行起来,可以采用spark自带的独立集群管理器,采用独立部署的模式: ...
- Linux pthread 线程池实现
基于pthread封装了一个简易的ThreadPool,具有以下特性: 1.具有优先级的任务队列 2.线程池大小可以二次调整,增加线程或者删除空闲线程 3.任务两种重写方式,重写run或者使用函数回调 ...
- redis基础和通用key操作
redis是什么? redis开源的,构建于内存的数据结构的nosql数据库.常被用于数据存储,缓存处理和消息处理. redis的优势? 1.极高的读写能力 2.丰富的数据类型 3.原子性操作 4.支 ...
- 文件特殊权限:SUID,SGID,SBIT
我们之前认识的文件的权限仅局限于r,w,x,但如果我们执行命令“ll /tmp; ll /usr/bin/passwd”,会出现除了r,w,x之外的其他字母: 即出现了特殊权限(s跟t). [SetU ...
- winform 控件半透明设置
1.backcolor属性为color.FromArgb(100, 220, 220, 220); 2.全透明设置为transparent方法.
- javascript实现自动切换焦点功能学习
当用户在表单中填写完当前字段后,能否自动将焦点跳转到下一个字段以方便用户输入? 为了增强易用性,加快数据输入的速度,可以在前一个文本框中的字符达到一定的设置的字符长度后(比如电话号码,身份证号等),用 ...