UVa 10306 e-Coins(二维完全背包)
题目:
有n种物品,每种物品有x, y两个价值,并且可以有无限多个。
给定s,使得(x1+x2+....)^2 + (y1+y2+....)^2 = s ^ 2。并且物品个数最少。
思路:
既然是物品个数没有限制,则就要想到完全背包。但是此时如何背包就要退而求解。
dp[i][j] 表示能选到x的总和为i,y的总和为j时,最少的物品选择数。
此时还有个隐性的物品背包属性,那就是个数:把物品的价值当作是背包容量,个数当作是价值。求能达到要求且价值最小的情况。
初始化状态:dp[0][0] = 0。
#include <cstdio> #include <cstdlib> #include <cstring> #include <climits> #define min(a,b) (((a) < (b)) ? (a) : (b)) const int MAXN = 301; int dp[MAXN][MAXN]; int w1[50], w2[50]; int main() { int cases; scanf("%d", &cases); while (cases--) { int m, S; scanf("%d %d", &m, &S); for (int i = 0; i < m; ++i) scanf("%d %d", &w1[i], &w2[i]); for (int i = 0; i <= S; ++i) for (int j = 0; j <=S; ++j) dp[i][j] = INT_MAX; dp[0][0] = 0; for (int i = 0; i < m; ++i) for (int v1 = w1[i]; v1 <= S; ++v1) for (int v2 = w2[i]; v2 <= S; ++v2) if (dp[v1-w1[i]][v2-w2[i]] != INT_MAX) dp[v1][v2] = min(dp[v1][v2], dp[v1-w1[i]][v2-w2[i]] + 1); int ans = INT_MAX; int t = S * S; for (int i = 0; i <= S; ++i) for (int j = 0; j <= S; ++j) if (i * i + j * j == t && dp[i][j] != INT_MAX) if (ans > dp[i][j]) ans = dp[i][j]; if (ans != INT_MAX) printf("%d\n", ans); else printf("not possible\n"); } return 0; }
-------------------------------------------------------
kedebug
Department of Computer Science and Engineering,
Shanghai Jiao Tong University
E-mail: kedebug0@gmail.com
GitHub: http://github.com/kedebug
-------------------------------------------------------