帮助_NOI导刊2010提高(03)

题目描述

Bubu的书架乱成一团了!帮他一下吧!

他的书架上一共有n本书。我们定义混乱值是连续相同高度书本的段数。例如,如果书的高度是30,30,31,31,32,那么混乱值为3,30,32,32,31的混乱度也是3,但31,32,31,32,31的混乱度是5-,这实在是太乱了。

Bubu想尽可能地减少混乱度,但他有点累了,所以他决定最多取出k本书,再随意将它们放到书架上。你能帮助他吗?

输入格式

最多会有20组测试数据。每组测试数据开头为两个整数n,k(l≤k≤n≤100),表示总共有n本书,最多可以进行k次搬书操作。接下来一行有n个整数,表示每本书的高度,从左到右。每本书的高度是25到32间的整数。最后一组数据后有一行n=k=0。

输出格式

对于每一组数据,输出Case标号和最终最小的混乱度。在每组数据后打印一个空行。

输入输出样例

输入 #1
    5 2
    25 25 32 32 25
    5 1
    25 26 25 26 25
    0 0
输出 #1
    Case 1:2
    Case 2:3

分析:
本题给定的数据显然让我们想到状态压缩DP,那么我们可以设计状态f[i][j][s][l],表示前i个选了j个状态为s最后一个为l所能得到最小的混乱度,然后进行状态转移即可。
然后发现我的代码最后一个点超时,死活过不去。。。所以我开了O2。。。
CODE:
 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<cmath>
 5 #include<cstring>
 6 using namespace std;
 7 const int M=120;
 8 const int N=265;
 9 int f[2][M][N][15];
10 int a[M],b[N];
11 int n,k,cnt;
12 int get(){
13     char c=getchar();
14     int res=0,f=1;
15     while (c>'9'||c<'0'){
16         if (c=='-') f=-1;
17         c=getchar();
18     }
19     while (c<='9'&&c>='0'){
20         res=(res<<3)+(res<<1)+c-'0';
21         c=getchar();
22     }
23     return res*f;
24 }
25 int main(){
26     for(int i=0;i<(1<<8);i++){
27         b[i]=0;
28         for(int j=0;j<8;j++)
29         if(i&(1<<j)) b[i]++;
30     }
31     while(~scanf("%d%d",&n,&k)&&(n+k)){
32         int S=0,maxn=0;
33         for(int i=1;i<=n;i++){
34             a[i]=get();
35             a[i]-=25;
36             S=S|(1<<a[i]);
37             maxn=max(maxn,a[i]);
38         }
39         maxn++;
40         memset(f[0],120,sizeof(f[0]));
41         f[0][1][0][maxn]=0;
42         f[0][0][(1<<a[1])][a[1]]=1;
43         int cur=0,pre=0;
44         for(int i=1;i<n;i++){
45             cur=pre^1;
46             memset(f[cur],120,sizeof(f[cur]));
47             for(int j=0;j<=k;j++){
48                 for(int s=0;s<=S;s++){
49                     for(int l=0;l<=maxn;l++){
50                         if(f[pre][j][s][l]==120) continue;
51                         f[cur][j][s|(1<<a[i+1])][a[i+1]]=min(f[cur][j][s|(1<<a[i+1])][a[i+1]],f[pre][j][s][l]+(a[i+1]==l?0:1));
52                         f[cur][j+1][s][l]=min(f[cur][j][s][l],f[pre][j][s][l]); 
53                     }
54                 }
55             }
56             pre=cur;
57         }
58         int ans=120;
59         for(int j=0;j<=k;j++){
60             for(int s=0;s<=S;s++){
61                 for(int l=0;l<maxn;l++){
62                     if(f[cur][j][s][l]==120)continue;
63                     int now=S^s;
64                     ans=min(ans,f[cur][j][s][l]+b[now]);
65                 }
66             }
67         }
68         printf("Case %d: %d\n\n",++cnt,ans);
69     }
70     return 0;
71 }

 



posted @ 2019-10-09 21:43  Sword_Art_Online  阅读(148)  评论(0编辑  收藏  举报