喜欢玩warcraft的ltl

喜欢玩warcraft的ltl

时间限制: 2000 ms  |  内存限制: 65535 KB
难度: 3
描述

ltl 非常喜欢玩warcraft,因为warcraft十分讲究团队整体实力,而他自己现在也为升级而不拖累团队而努力。

他现在有很多个地点来选择去刷怪升级,但是在每一个地点他都要买上充足的补给和合适的道具,以免在刷怪的时候被怪物反杀了,每一个地点的怪物打完了就没有了(还居然不掉金钱跟装备),而且他只要选定了地点就一定会刷完该地点全部的怪物,同时获得对应的经验值。现在ltl 能给出每一个地点用来买补给和道具的钱和打完全部怪物所能获得的经验,但是他所拥有的钱是一定的。所以他想知道怎么选择地点使得他获得的经验最高。

输入
第一行一个整数T,表示测试数据的组数 0<T<=10
第二行两个整数N,M,0<N<=100,0<M<=1000000表示ltl拥有N个不同地点的选择和M的金钱总数
接下来N行每行两个整数ci,vi,(0<ci<=1000000,0<vi<=2000)表示ltl刷完第i个地点所需要购买补给和道具的总钱数和能获取的总经验值
输出
一行一个整数,表示ltl能够获取的最大的经验值
样例输入
2
3 10
7 7
2 3
3 5
2 5
3 5
2 1
样例输出
Max experience: 12

Max experience: 6

/*一个常数优化前面的伪代码中有for v=V..1,可以将这个循环的下限进行改进。
由于只需要最后dp[v]的值,倒推前一个物品,其实只要知道dp[v-w[n]]即可。以此类推,对以
第j个背包,其实只需要知道sumc[i->n](第i物品到最后一个物品的消耗和,因为前面的对结果没有影响)即可,即代码中的

1 for i -> 1 to N
2     do for v -> V to 0
3         do

可以改成:

1 for i -> 1 to n
2     do bound -> max(V - sumc[i->n], c[i])
3     for v -> V to bound
4         do
这对于V比较大时是有用的。
----- 摘自《背包问题九讲v1.1》
*/

#include <stdio.h>
#include <string.h>

int dp[1000001], value[101], cost[101];

int main()
{
    int t, n, m, i, j, temp, sum;
    scanf("%d", &t);
    while(t--)
    {
        memset(dp, 0, sizeof(dp));
        sum = 0;
        scanf("%d%d", &n, &m);
        for(i = 0; i < n; i++)
        {
            scanf("%d%d", &cost[i], &value[i]);
            sum += cost[i];
        }
        for(i = 0; i < n; i++)
        {
            sum -= cost[i];
            temp = m-sum > cost[i] ? m-sum : cost[i];    //此处优化
            for(j = m; j >= temp; j--)
            {
                if(dp[j-cost[i]]+value[i] > dp[j])
                {
                    dp[j] = dp[j-cost[i]]+value[i];
                }
            }
        }
        printf("Max experience: %d\n", dp[m]);
    }
    return 0;
}


你可能感兴趣的:(dp)