zoukankan      html  css  js  c++  java
  • hdu6376 度度熊剪纸条-----01背包

    题目:

       度度熊有一张纸条和一把剪刀。


        纸条上依次写着 N 个数字,数字只可能是 0 或者 1。
     
        度度熊想在纸条上剪 K 刀(每一刀只能剪在数字和数字之间),这样就形成了 K+1 段。

        他再把这 K+1 段按一定的顺序重新拼起来。

        不同的剪和接的方案,可能会得到不同的结果。

        度度熊好奇的是,前缀 1 的数量最多能是多少。   

    Input
      有多组数据,读到EOF结束。
      对于每一组数据,第一行读入两个数 N 和 K 。
      第二行有一个长度为 N 的字符串,依次表示初始时纸条上的N个数。0≤K<N≤10000所有数据N的总和不超过100000
    Output
      对于每一组数据,输出一个数,表示可能的最大前缀 1 的数量。

    Sample Input
    5 1
    11010
    5 2
    11010
    Sample Output
    2
    3


    经过分析,不难看出,这道题实际上是在考 01背包。怎么是01背包呢?我们可以这么看:

    可以把 1 的组数作为物品个数,每组里 1 的个数 作为每个物品的权值,然后把 剪 k 次 作为体积。这样的话貌似跑一遍零一背包就可以了。

    这么简单吗......

    然而枚举几个例子之后发现果然没那么简单....

    就比如 1011101 ,现在让你只剪 1 刀,显然我们要剪成 10 和 111011,然后拼成 11101110,这样得到正确答案 3。而01背包的话,你根本不能剪出来 111。

    根据这个例子,我们发现,这么多组1中,最后可以让其中一组1作为开头,那么那一组1的真实代价就会-1。那难道我们要一一枚举每一组1吗?

    其实不然。我们把背包容量+1,就相当于其中一个物品的代价-1。这两种操作是等效的。

    嗯,那就没问题了:背包体积+1,然后跑01背包。

    代码:

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cmath>
    #include <cstring>
    using namespace std;
    const int MAXN = 1e4 + 3;
    
    int n, k, v[MAXN], w[MAXN], f[MAXN], cnt;
    char a[MAXN];
    
    int main(){
        while(scanf("%d%d",&n,&k) != EOF){
            memset(a, 0, sizeof(a));
            memset(f, 0, sizeof(f));
            memset(w, 0, sizeof(w));
            memset(v, 0, sizeof(v));
            cnt = 0;
    
            scanf("%s",a+1);
            for(int i=1;i<=n;i++){
                if(a[i]=='1'){
                    cnt++;
                    v[cnt] = 2;
                    while(a[i]=='1' && i<n+1){
                        i++;
                        w[cnt]++;
                    }
                }
            }
            if(a[1]=='1') v[1]=1;
            if(a[n]=='1') v[cnt]=1;
    
            if(++k == 1){
                if(a[1]=='1'){
                    printf("%d
    ",w[1]); continue;
                }else{
                    printf("0
    "); continue;
                }
            }
            for(int i=1;i<=cnt;i++){
                for(int j=k;j>=v[i];j--)
                    f[j] = max(f[j], f[j-v[i]]+w[i]);
            }
            printf("%d
    ",max(f[k],0));
        }
        
        return 0;
    }
  • 相关阅读:
    apache安装 解决无services
    需要看的书
    rbac
    IDocHostShowUI
    Eclipse快捷键大全
    Linux中vi显示中文乱码的问题
    如何编译安装Go语言
    ubuntu11.04 下LAMP 开发环境配置
    网络内核sk_buff结构体
    查看所有表名,查询结果加上字符
  • 原文地址:https://www.cnblogs.com/Siegfried-L/p/12714992.html
Copyright © 2011-2022 走看看