状压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 题意:一个人到一些地方送披萨,要求找到一条路径能够遍历每一个城市后返回出发点,并且路径距离最短.最后输出最短距离即可.注意:每一 ...
随机推荐
- PHP批量替换MySql数据库中的数据内容
<?php //替换数据库内容类 class replace{ public $dbAddress; //数据库地址 public $dbUser; //数据库用户名 public $dbPwd ...
- vs2015-Cordova开发安卓应用环境搭建
之前看到过用html5+css+js就可以开发跨平台的应用,然后发现vs2015里就有个Cordova项目所以就想试试,但并不是这么顺利.刚开始对安卓环境一点也不了解,就到处百度搜索.终于成功了. 首 ...
- C++学习005-循环
C++在循环方面,感觉个C没有身边么区别 while循环 for循环 do while循环 其实 使用Goto也可以写个循环 编写环境vs2015 1. while循环 int main() { in ...
- Struts2(四.注册时检查用户名是否存在及Action获取数据的三种方式)
一.功能 1.用户注册页面 <%@ page language="java" contentType="text/html; charset=UTF-8" ...
- (转)Unreal Networking Guide Created by Zach Metcalf
2. 3.
- ZooKeeper的伪分布式集群搭建
ZooKeeper集群的一些基本概念 zookeeper集群搭建: zk集群,主从节点,心跳机制(选举模式) 配置数据文件 myid 1/2/3 对应 server.1/2/3 通过 zkCli.sh ...
- HDU 3696 Farm Game(拓扑+DP)(2010 Asia Fuzhou Regional Contest)
Description “Farm Game” is one of the most popular games in online community. In the community each ...
- POJ 1144 Network(割点)
Description A Telephone Line Company (TLC) is establishing a new telephone cable network. They are c ...
- PHP全局变量局部变量
http://www.w3school.com.cn/php/php_variables.asp
- Mybatis学习系列(六)延迟加载
延迟加载其实就是将数据加载时机推迟,比如推迟嵌套查询的执行时机.在Mybatis中经常用到关联查询,但是并不是任何时候都需要立即返回关联查询结果.比如查询订单信息,并不一定需要及时返回订单对应的产品信 ...