状压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 题意:一个人到一些地方送披萨,要求找到一条路径能够遍历每一个城市后返回出发点,并且路径距离最短.最后输出最短距离即可.注意:每一 ...
随机推荐
- git删除本地及远程分支
1. 删除本地分支: git branch -d branchName 2. 删除远程分支: // 方法一:将删除的本地分支推到远程(要删除的远程分支在本地有映射) git push origin : ...
- C++各种类型的简单排序大汇总~
啊,排序的技能点也太多了吧!!!LITTLESUN快要**在排序的技能场了啊!(划掉)经历了两天48小时2880分钟172800秒的艰苦奋斗,终于终于终于学的差不多了!明天就可以去打排序的小怪喽!(撒 ...
- laravel读excel
fileName = "test.xls";$filePath = "../storage/app/";Excel::load($filePath.$fileN ...
- Android Open Source Projects(汇总与整理)
Android Open Source Projects 目前包括: Android开源项目第一篇——个性化控件(View)篇 包括ListView.ActionBar.Menu.ViewPager ...
- SSH公钥认证(码云)
开发者向码云版本库写入最常用到的协议是 SSH 协议,因为 SSH 协议使用公钥认证,可以实现无口令访问,而若使用 HTTPS 协议每次身份认证时都需要提供口令.使用 SSH 公钥认证,就涉及到公钥的 ...
- PHP的array_merge()合并数组
,4];print_r(array_merge($arr1,$arr2));返回结果:Array( [a] => 3 [b] => 2 [0] => 4)1注释:当 ...
- C++学习006-条件运算符
这里我也理解的不咋的,大致意思应该就是根据运算符号 的优先级不同来解决的 条件运算符是其中一部分,而条件运算符具有右结合性,当一个表达式中出现多个条件运算符时,应该将位于最右边的问号与理他最近的冒号配 ...
- 【性能调优】一次关于慢查询及FGC频繁的调优经历
以下来分享一个关于MySQL数据库慢查询和FGC频繁的性能案例. 一.系统架构 一个简单的dubbo服务,服务提供者提供接口,并且提供接口的实现,提供方注册服务到Zookeeper注册中心,然后消费者 ...
- MySQL☞insert value与values
最近公司事情太忙,作为以一挑十的测试,只能苦逼的累死累活的.好不容易临近上线,可以偷个懒写个文章. 简单的说说如何向表中插入数据: 1.向表中所有的列插入数据(插入多行数据): insert int ...
- Elasticsearch中的DocValues
Elasticsearch最近一段时间非常火,以致于背后的公司都改名为Elastic了,因为Elasticsearch已经不仅限于搜索,反而更多的用在大数据分析场景,所以在公司品牌上开始“去Searc ...