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 }
代码君

 

posted @ 2015-08-04 17:44  AOQNRMGYXLMV  阅读(353)  评论(0编辑  收藏  举报