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

题目: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和Y
	return 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");
		else
			printf ("%d\n", ans);
	}
	return 0;
}

          

你可能感兴趣的:(uva10306 - e-Coins(记忆化搜索))