andre_joy

导航

zoj 3623

地址:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4769

题意:输入n,l,n代表有n种船可以造,l代表怪物的血量。再输入n行,每行两个数,分别代表造船的时间和船的攻击力,船造好之后可以一直攻击敌人,求打死敌人的最短时间。

mark:这居然是个完全背包的题。真的是没想到,看解题报告看了好久才看懂。

   把每条船时间当成体积,攻击力当成价值,dp[j]存放时间j最多能打敌人多少血。dp[j] = max(dp[j], dp[j-v[i]]+(j-v[i])*w[i]);

   分析:这个转换的时候可以这样理解,后面加的(j-v[i])*w[i]是说第一秒的时候造的i船,然后它可以攻击(j-v[i])秒,所以造成的伤害是(j-v[i])*w[i],则dp[j-v[i]]就代表除去第一秒造i船的伤害,别的在时间j内的伤害最大值。(仔细体会体会……)

   还有的解题报告说dp[i][j]可以代表怪物掉了i血,当前攻击力为j的时候最小的时间。则dp[i][j] = min(dp[i][j], dp[i-t[k]*(j-l[k])][j-l[k]]), (0 <= k < n);意思是最后一次造的k船,则在准备造这条船的时候的状态就是dp[i-t[k]*(j-l[k])][j-l[k]].代码就不给了。http://blog.csdn.net/wconvey/article/details/7804524

代码:

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

const int N = 35;
const int M = 1000;
int n,l;
int v[N],w[N];
int dp[M];

int max(int a, int b) {return a > b ? a : b;}

int main()
{
    int i,j,k;
    while(~scanf("%d%d", &n, &l))
    {
        for(i = 0; i < n; i++)
            scanf("%d%d", v+i, w+i);
        memset(dp, 0, sizeof(dp));
        for(i = 0; i < n; i++)
            for(j = v[i]; j <= v[i]+l; j++)
                dp[j] = max(dp[j], dp[j-v[i]]+(j-v[i])*w[i]);
        for(i = 0; i < v[i]+330; i++)
            if(dp[i] >= l)
            {
                printf("%d\n", i);
                break;
            }
    }
    return 0;
}

posted on 2012-09-25 10:49  andre_joy  阅读(393)  评论(0编辑  收藏  举报