UVa 12235 状压DP Help Bubu

题解戳这

一开始没看懂题解,后来想明白以后,d(i, j, s, x)是考虑第i本书的时候,前面已经拿走了j本书,剩下的书的种类的二进制状态为s,剩下的最后一本书的编号为x,所能得到的最小混乱度。

这里状态定义的时候,先不考虑把拿出来的书放回去。

最后统计答案的时候,把那些拿出来的书再加上。

all是所有n本书的状态,s是剩下书的种类的状态。

如果拿出来的书中有和前面高度相同的,直接插到相邻的位置就行了,不会增加混乱度。

如果拿出来的书中没有和前面高度相同的,不管放在那里混乱度都会加1,这样所增加的混乱度就是bitcount(all ^ s)

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5
 6 const int maxn = 100 + 5;
 7 const int maxs = (1 << 8);
 8 const int INF = 0x3f3f3f3f;
 9
10 int n, k;
11
12 int a[maxn];
13 int d[2][maxn][maxs][8];
14
15 int bitcount(int x)
16 {
17     int ans = 0;
18     while(x) { ans += (x&1); x >>= 1; }
19     return ans;
20 }
21
22 int main()
23 {
24     int kase = 0;
25
26     while(scanf("%d%d", &n, &k) == 2)
27     {
28         if(!n && !k) break;
29
30         for(int i = 0; i < n; i++) scanf("%d", a + i);
31
32         memset(d[0], 0x3f, sizeof(d[0]));
33         int cur = 0;
34         int all = 0;
35
36         for(int i = 0; i < n; i++)
37         {
38             cur ^= 1;
39             memset(d[cur], 0x3f, sizeof(d[cur]));
40             int h = a[i] - 25;
41             d[cur][i][1<<h][h] = 1;
42
43             for(int j = 0; j <= min(k, i); j++)
44                 for(int s = all; s; s = (s-1)&all)
45                     for(int x = 0; (1 << x) <= s; x++)
46                         if(d[cur^1][j][s][x] != INF)
47                         {
48                             int t = d[cur^1][j][s][x];
49                             if(x == h) d[cur][j][s][x] = min(d[cur][j][s][x], t);
50                             else
51                             {
52                                 d[cur][j+1][s][x] = min(d[cur][j+1][s][x], t);
53                                 d[cur][j][s|(1<<h)][h] = min(d[cur][j][s|(1<<h)][h], t + 1);
54                             }
55                         }
56             all |= (1 << h);
57         }
58
59         int ans = n;
60         for(int j = 0; j <= k; j++)
61             for(int s = all; s; s = (s-1)&all)
62                 for(int x = 0; (1 << x) <= s; x++)
63                     ans = min(ans, d[cur][j][s][x] + bitcount(all^s));
64         printf("Case %d: %d\n\n", ++kase, ans);
65     }
66
67     return 0;
68 }

代码君

时间: 2024-09-30 16:51:10

UVa 12235 状压DP Help Bubu的相关文章

UVa 10817 (状压DP + 记忆化搜索) Headmaster&#39;s Headache

题意: 一共有s(s ≤ 8)门课程,有m个在职教师,n个求职教师. 每个教师有各自的工资要求,还有他能教授的课程,可以是一门或者多门. 要求在职教师不能辞退,问如何录用应聘者,才能使得每门课只少有两个老师教而且使得总工资最少. 分析: 因为s很小,所以可以用状态压缩. dp(i, s1, s2)表示考虑了前i个人,有一个人教的课程的集合为s1,至少有两个人教的集合为s2. 在递归的过程中,还有个参数s0,表示还没有人教的科目的集合. 其中m0, m1, s0, s1, s2的计算用到位运算,还

UVa 11825 (状压DP) Hackers&#39; Crackdown

这是我做状压DP的第一道题,状压里面都是用位运算来完成的,只要耐下心来弄明白每次位运算的含义,还是容易理解的. 题意: 有编号为0~n-1的n台服务器,每台都运行着n中服务,每台服务器还和若干台其他服务器相连.对于每台服务器,你可以选择停止该台以及与这台服务器相连的服务器的一项服务.如果一台服务器的所有服务都被停止,则这台服务器瘫痪.问最多能使多少台服务器瘫痪 转化为数学模型(题目是如何抽象成这种数学模型的也要好好想想): 把n个集合尽可能多的分成若干组,使得每组所有集合的并集为全集.这里集合P

Sharing Chocolate - UVa 1099 状压dp

Chocolate in its many forms is enjoyed by millions of people around the world every day. It is a truly universal candy available in virtually every country around the world. You find that the only thing better than eating chocolate is to share it wit

UVa 1252 (状压DP + 记忆化搜索) Twenty Questions

题意: 有n个长为m的各不相同的二进制数(允许存在前导0),别人已经事先想好n个数中的一个数W,你要猜出这个数. 每次只可以询问该数的第K为是否为1. 问采用最优询问策略,则最少需要询问多少次能保证猜到. 比如有1100 和 0110两个数,只需要询问第一或第三位数是否为1,即可猜中,因此答案为1. 分析: d(s, a)表示已经询问了的集合s,在已经询问了的集合中W中为1的集合为a,还需要询问多少次. 如果下一次询问第k位,则询问次数为: 然后取所有k里的最小值即可. 预处理: 对于每个s和a

UVA - 1412 状压dp九进制表示状态

此题难点在于用九进制表示状态,并且转移 这里九进制用vector表示,再用map作为此状态特有的标记 此处用刷表法,每一种状态转移都经历一遍,最终状态就是正确答案,注意界限 #include<iostream> #include<cstdio> #include<cstring> #include<string> #include<map> #include<stack> #include<queue> #include&

UVA - 11825 状压DP

该题目是EMAXX推荐的练习题,刘汝佳的书也有解说 如果S0属于全集,那S0就可以作为一个分组,那么S分组数可以是best{当前S中S0的补集+1} 对于集合类的题目我觉得有点抽象,希望多做多理解把 #include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<

(状压dp)uva 10817 Headmaster&#39;s Headache

题目地址 1 #include <bits/stdc++.h> 2 typedef long long ll; 3 using namespace std; 4 const int MAX=1e5+5; 5 const int INF=1e9; 6 int s,m,n; 7 int cost[125]; 8 //char sta[MAX]; 9 string sta; 10 int able[125]; 11 int dp[125][1<<8][1<<8]; 12 in

UVA 10817 Headmaster&#39;s Headache 状压DP

记录两个状态S1,S2分别记录哪些课程被1个人教过或2个人教过,然后记忆化搜索 UVA - 10817 Headmaster's Headache Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu Submit Status Description Problem D: Headmaster's Headache Time limit: 2 seconds The headmaster of Spr

【UVa】Headmaster&#39;s Headache(状压dp)

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1758 晕....状压没考虑循环方向然后错了好久.. 这点要注意...(其实就是01背包变成了完全背包QAQ 我们将课程拆成两个点,然后状压 那么答案就是(1<<(s<<1))-1 转移就不说了,,,,,太简单.. #include <cstdio> #in