uva10306 - e-Coins(记忆化搜索)

来源:互联网 发布:聚丙烯看盘软件下载 编辑:程序博客网 时间:2024/05/11 17:13

题目:uva10306 - e-Coins(记忆化搜索)


题目大意:给出N个硬币,每个硬币有对应的X和Y,ecoin的值= Sqrt(X * X + Y * Y).问这些硬币能否得到给定的ecoin。能的话输出最小的组成数目。不能酒输出Not possible。


解题思路:这里的X和Y并不是指定是一个硬币的X或Y,可以是多个硬币来组成这个ecoin的值。例如 3 0 和 0 4 是可以组成ecoin5的。

                  所以这里用dp【x】【y】表示达到X和Y这个状态时,最少要几个coin。     

                  dp【x】【y】 = Min (dp【x - v【i】.x】dp【y - v【i】.y] + 1)  【i >= 1 && i <= m】 , m 代表给定的硬币的个数。

                  对于给定的ecoin,就要找出满足 X * X + Y * Y = ecoin的所有的X。然后用记忆化搜索一下答案,取最小值。这里有找不到的情况,也有没有找的情况。这两个情况要区分开。  


代码:

#include <cstdio>#include <cmath>#include <cstring>const int N = 45;const int maxn = 305;const int INF = 0x3fffffff;int value[N][2];int dp[maxn][maxn];int n, s;int Min (const int a, const int b) { return a < b ? a: b; }void init () {for (int i = 0; i <= s; i++)for (int j = 0; j <= s; j++)dp[i][j] =INF;  //代表没找过的for (int i = 0; i < n; i++)dp[value[i][0]][value[i][1]] = 1;/*printf ("%d\n", s);for (int i = 0; i <= s; i++) {for (int j = 0; j <= s; j++)printf ("%d ", dp[i][j]);printf ("\n");}*/}int DP (int x, int y) {int& ans = dp[x][y];  if (ans != INF)return ans;int x1, y1;for (int i = 0; i < n; i++) {x1 = value[i][0];y1 = value[i][1];if (x >= x1 && y >= y1)ans = Min (ans, DP(x - x1, y - y1) + 1); }if (ans == INF)ans = INF + 1;   //代表这些硬币不论怎么组成都不能得到这样的X和Yreturn ans;}int main () {int t;scanf ("%d", &t);int ans;while (t--) {scanf ("%d%d", &n, &s);for (int i = 0; i < n; i++) scanf ("%d%d", &value[i][0], &value[i][1]);init ();ans = INF;int y;for (int x = 0; x <= s; x++) {y = (int) sqrt (s * s - x * x);if (y * y + x * x == s * s) ans = Min (ans, DP(x, y));}if (ans == INF)printf ("not possible\n");elseprintf ("%d\n", ans);}return 0;}

          

0 0
原创粉丝点击