Sicily 1221. 数字游戏

直观上觉得应该优先选取b大的那个数字,这样a就不会下降的太快,但是这种情况仅仅适用于n=m的时候。因为我们需要的是m个数字的a值之和是最大的,当n>m时,如果直接选取了下降速度最快(即b最大)的那m个数字,有可能后面的数的a值可能仍然很大,但b值却很少,这样就不能保证这m个数的a值之和是最大的(而当n=m是却不存在这个问题)。

从另一个角度看,问题的本质在于选取哪m个数字,也即是该不该选取某一个数字,这明显是01背包的特点。当使用一维数组来解决这个问题时,鉴于数组上的数据是覆盖保存的,首先就要对每个数字按b值从大到小进行排序,从而确保迭代过程中的数据都是目前最优的。状态转移方程则是:score[j]=max(score[j],score[j-1]+a[i]-b[i]*(j-1)),理解为对于第i个数字,当要选取j个数字时,最优结果是:不选取这个数字,从剩下的数字中再选取j个数字的最优结果;或者是选取这个数字,从剩下的数字中再选取j-1个数字的最优结果。以上两者的更优者就是最优解。如此进行下去,score[m]就是最终解。

Run Time: 0sec

Run Memory: 312KB

Code Length: 707Bytes

SubmitTime: 2012-02-13 16:17:25

// Problem#: 1221
// Submission#: 1210144
// The source code is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
// URI: http://creativecommons.org/licenses/by-nc-sa/3.0/
// All Copyright reserved by Informatic Lab of Sun Yat-sen University
#include <iostream>
#include <algorithm>
using namespace std;

struct Num {
    int a;
    int b;
};

bool cmp( const Num& n1, const Num& n2 ) { return n1.b > n2.b; }

int main()
{
    int n, m;
    Num num[ 201 ];
    int score[ 201 ];
    int i, j;

    cin >> n >> m;
    for ( i = 1; i <= n; i++ )
        cin >> num[ i ].a;
    for ( i = 1; i <= n; i++ )
        cin >> num[ i ].b;
    sort( num + 1, num + n + 1, cmp );

    for ( i = 0; i <= m; i++ )
        score[ i ] = 0;
    for ( i = 1; i <= n; i++ ) {
        for ( j = m; j >= 1; j-- )
            score[ j ] = max( score[ j ], score[ j - 1 ] + num[ i ].a - num[ i ].b * ( j - 1 ) );
    }
    cout << score[ m ] << endl;
    
    return 0;

}                                 


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值