zoukankan      html  css  js  c++  java
  • 洛谷 P1987 摇钱树

    题目

    题目描述

    Cpg 正在游览一个梦中之城,在这个城市中有n棵摇钱树。。。这下,可让Cpg看傻了。。。可是Cpg只能在这个城市中呆K天,但是现在摇钱树已经成熟了,每天每棵都会掉下不同的金币(不属于Cpg!)。Cpg每天可以砍掉其中一颗,并获得其树上说有的金币(怎么会有这种好事。。。)。请你帮助Cpg算出他在这K天中最多能获得多少金币。

    输入输出格式

    输入格式:

    每个文件中有不超过10组测试数据。

    每组测试数据:

    第一行两个整数n,K (1<=K<=n<=1000)

    第二行n个整数Mi (Mi <= 100000).表示Cpg刚看到这n棵树时每刻树上的金币数。

    第三行n个整数 Bi.(Bi<=1000)表示每颗摇钱树,每天将会掉落的金币。

    以n=K=0结束。

    输出格式:

    对每组测试数据,输出仅一行,Cpg在K天中能获得的最大金币数。

    输入输出样例

    输入样例#1:

    3 3
    10 20 30
    4 5 6
    4 3
    20 30 40 50
    2 7 6 5
    0 0
    

    输出样例#1:

    47 104

    Solution:

    首先,吐槽一下题目数据,没有指出Mi>=Bi,大家应该把这个当作隐藏条件。至于思路,我们先思考,很明显若只选1棵树,那就选价值最大的,若要选多棵树,则要先选消耗最大的(不一定价值最大)。为什么呢?假设我们有3棵树且要选全部,每棵价值和每次消耗分别为m1,m2,m3;b1,b2,b3;则总价值=m1+m2+m3-k1*b1-k2*b2-k3*b3,其中k为第几次选-1,很明显消耗的大的系数要小,即消耗大的要先取。以此我们可以推及到n棵树选k棵的情况(明显就是dp了嘛),先按消耗从大到小贪心排序,这样去取肯定保证最优,然后考虑dp,设f[i][j]表示前i棵树选j棵得到的最大值,则很容易得到状态转移方程:f[i][j]=max(f[i-1][j],f[i-1][j-1]+max(0,m[i]-b[i]*(j-1))) 。

    代码:

     1 #include<bits/stdc++.h>
     2 #pragma GCC optimize(2)
     3 using namespace std;
     4 #define ll long long
     5 #define il inline
     6 int n,k,a[1005],p[1005],f[1005][1005],ans;
     7 struct pig{
     8 int a,p;
     9 }zhu[1005];
    10 il bool cmp(pig a,pig b){return a.p>b.p;}
    11 il int gi()
    12 {
    13     int a=0;char x=getchar();bool f=0;
    14     while((x<'0'||x>'9')&&x!='-')x=getchar();
    15     if(x=='-')x=getchar(),f=1;
    16     while(x>='0'&&x<='9')a=a*10+x-48,x=getchar();
    17     return f?-a:a;
    18 }
    19 il int max(int a,int b){if(a>b)return a;return b;}
    20 int main()
    21 {
    22     while(1){
    23         n=gi(),k=gi();
    24         if(n==0&&k==0)return 0;
    25     ans=0;
    26     memset(f,0,sizeof(f));
    27     for(int i=1;i<=n;i++)zhu[i].a=gi();
    28     for(int i=1;i<=n;i++)zhu[i].p=gi();
    29     sort(zhu+1,zhu+n+1,cmp);
    30     for(int i=1;i<=k;i++)
    31     for(int j=1;j<=n;j++)
    32     {
    33         int x=zhu[j].a-zhu[j].p*(i-1);
    34         x=x>0?x:0;
    35         f[j][i]=max(f[j-1][i],f[j-1][i-1]+x);
    36     }
    37     for(int i=1;i<=k;i++)ans=max(f[n][i],ans);
    38     printf("%d
    ",ans);
    39     }
    40     return 0;
    41 }
  • 相关阅读:
    eclipse或adt-bundle创建的android项目没有自动生成MainActivity.java和activity_main.xml等文件解决办法
    递归遍历删除注册表项和键值
    注册表:无法打开 XXX 由于某个错误无法打开该密钥。详细信息:拒绝访问
    connot find one or more components. please reinstall the application
    Couldn't load libPassword from loader:NDK开发中C文件编译成cpu对应的so类库时,找不到类库报错的原因之一
    通用组合算法
    Chance – 功能强大的 JavaScript 随机数生成类库
    shell中各种括号的作用()、(())、[]、[[]]、{}
    iftop监控网络流量命令
    Linux—shell中$(( ))、$( )、``与${ }的区别
  • 原文地址:https://www.cnblogs.com/five20/p/7804548.html
Copyright © 2011-2022 走看看