UVa 10154 Weights and Measures(经典DP)

题意:

有n只乌龟,每只乌龟有个体重w以及力量s,乌龟所能承载的最大重量就是s,包括其体重。

问乌龟最多能叠几层?

思路:

http://geotakucovi.com/oi/?p=142

首先要对乌龟的力量从小到大排序。于是dp[i, j]表示前i只乌龟叠j层所能达到的最小体重,不能叠j层则用INT_MAX表示。

有了这个转移方程的定义,问题一下子就变得明朗了,只能感叹自己关于动归的思路还是不够成熟。不知道如何变相思考问题。

dp[i, j] = min(dp[i-1, j], dp[i-1, j-1] + wi); 前提是i可以承载i-1

仔细品味,其实本质上就是拿i与不拿i的区别,前面的很多我认为经典的题目也都是体现了这一思想,如何围绕这个点进行雕琢,需仔细思考。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <climits>

using namespace std;

const int MAXN = 5610;

struct Node {
    int w, s;
    friend bool operator < (const Node &a, const Node &b) {
        return a.s < b.s;
    }
} ele[MAXN];

int dp[MAXN][MAXN];

int main()
{
    int w, s;
    int n = 0;
    while (scanf("%d %d", &w, &s) != EOF)
        ele[++n].w = w, ele[n].s = s;
    
    sort(ele + 1, ele + n + 1);
    
    for (int i = 0; i <= n; ++i)
    {
        dp[i][0] = 0;
        for (int j = 1; j <= n; ++j)
            dp[i][j] = INT_MAX;
    }

    for (int i = 1; i <= n; ++i)
    {
        for (int j = 1; j <= i; ++j)
        {
            dp[i][j] = dp[i-1][j];
            if (ele[i].s - ele[i].w >= dp[i-1][j-1] && dp[i-1][j-1] != INT_MAX)
                dp[i][j] = min(dp[i][j], dp[i-1][j-1] + ele[i].w);
        }
    }
    int ans = 0;
    for (int i = n; i >= 1; --i)
        if (dp[n][i] != INT_MAX) {
            ans = i;  break;
        }

    printf("%d\n", ans);
    return 0;
}

 

 

posted @ 2012-11-20 23:00  kedebug  阅读(1275)  评论(0编辑  收藏  举报