zoukankan      html  css  js  c++  java
  • 饭卡(0 1背包)

    科大本部食堂的饭卡有一种很诡异的设计,即在购买之前判断余额。如果购买一个商品之前,卡上的剩余金额大于或等于5元,就一定可以购买成功(即使购买后卡上余额为负),否则无法购买(即使金额足够)。所以大家都希望尽量使卡上的余额最少。
    某天,食堂中有n种菜出售,每种菜可购买一次。已知每种菜的价格以及卡上的余额,问最少可使卡上的余额为多少。
    Input多组数据。对于每组数据:
    第一行为正整数n,表示菜的数量。n<=1000。
    第二行包括n个正整数,表示每种菜的价格。价格不超过50。
    第三行包括一个正整数m,表示卡上的余额。m<=1000。

    n=0表示数据结束。
    Output对于每组输入,输出一行,包含一个整数,表示卡上可能的最小余额。Sample Input
    1
    50
    5
    10
    1 2 3 2 1 1 2 3 2 1
    50
    0
    Sample Output
    -45
    32



    很容易看出来是0 1背包,但不完全是0 1背包,属于0 1背包的变形;

    对于给定的金钱m,可以考虑先从m中拿出来5元,那5元作为最后用来支付开销最大的饭。那用(m-5)d的钱来购买除开销最大饭以外的饭。也就是0 1背包求价值最大。

    但是为什么把开销最大的饭作为杀手锏最后花一定是最优的呢?下面我来给出证明

    ①假设杀手锏(也就是用5元买的饭)是开销最大的饭。

    ②假设杀手锏不是开销最大的饭。

    如果说杀手锏是开销最大的饭,那么思路就跟上面说说的一样,

    如果杀手锏不是开销最大的饭设其值为v”,(开销最大的设为V.max),n那么这种情况下V.max一定包含在背包内了(如果在背包外,那杀手锏也不会让v"出手),如果我现在让v"与V.max换换位置(V.max在背包中占的位置大,v"一定可以与他交换),那么造成的价值是不变的,也就是说情况②又回归到了情况①上

    所以说杀手锏必定是开销最大的饭。

    就照着黑体字的思路开始写代码(注意m<5时是用不了杀手锏的)

    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    #define N 1010
    #define INF 0x3f3f3f3f
    using namespace std;
    int dp[N];
    int val[N];
    int book[N];//表示对应标号能不能用(1为不能用)
    int main()
    {
        int n,maxx,u,m;
        while(~scanf("%d",&n)&&n)
        {
            memset(book,0,sizeof(book));
            memset(dp,0,sizeof(dp));
            maxx=-INF;
            for(int i=0;i<n;i++)
            {
                scanf("%d",&val[i]);
                if(val[i]>maxx)
                {
                    u=i;
                    maxx=val[i];
                }
            }
            book[u]=1;
            cin>>m;
            if(m<5)
            {
                cout<<m<<endl;
                continue;
            }
            m-=5;
            for(int i=0;i<n;i++)//枚举背包
            {
                if(book[i])
                    continue;
                for(int j=m;j>=val[i];j--)
                {
                    dp[j]=max(dp[j-val[i]]+val[i],dp[j]);//最后的值表示为用m-5最多能选多少元的菜
                }
            }
    
            cout<<m+5-dp[m]-val[u]<<endl;
        }
    }
    

  • 相关阅读:
    asp.net 网页标题、关键字、描述
    星级评分jQuery插件
    以jquery为基础的星星评分
    投票系统显示结果jQuery插件
    JAVASCRIPT模拟模式对话窗口
    Repeater 嵌套代码
    window服务程序安装卸载批处理文件
    c#window程序开发入门系列自学笔记
    jquery 模式对话框改进版
    php的正则表达式完全手册
  • 原文地址:https://www.cnblogs.com/dchnzlh/p/9780076.html
Copyright © 2011-2022 走看看