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; }
-------------------------------------------------------
kedebug
Department of Computer Science and Engineering,
Shanghai Jiao Tong University
E-mail: kedebug0@gmail.com
GitHub: http://github.com/kedebug
-------------------------------------------------------