zoukankan      html  css  js  c++  java
  • 帮助_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
    
    ",++cnt,ans);
    69     }
    70     return 0;
    71 }


  • 相关阅读:
    C++中逻辑操作符的重载分析
    不要62
    P1052 过河
    P1029 最大公约数和最小公倍数问题
    P1345 [USACO5.4]奶牛的电信Telecowmunication
    Dining
    Dinic
    [Scoi2015]小凸玩矩阵
    12.16
    bzoj 3529
  • 原文地址:https://www.cnblogs.com/kanchuang/p/11644580.html
Copyright © 2011-2022 走看看