UVA 10306 e-Coins

大意不再赘述。

思路:二维完全背包。一开始我以为用1维完全背包去求解,第二组测试数据过不了,后来发现这样处理有点困难。先定下来一定是背包问题,然后思考其他的解决方案,思考了好久,就是满足勾股定理这儿不好解决,后来干脆不管啥勾股定理,定义一个二维背包,直接将所有的最优值算出来,最后取满足勾股定理的值。

转移方程:f[i][j] = min(f[i][j], f[i-cost1][j-cost2]+1),与一维完全背包类似,这里表示当前背包容量为i,j时的物品的最小值。

初始化时,一定是装满背包,所以f[i][j] = INF, f[0][0] = 0

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <cstring>
using namespace std;

const int INF = 0x3f3f3f3f;
const int MAXN = 1010;

int V1[MAXN], V2[MAXN];
int f[MAXN][MAXN];

int n, C;

void init()
{
	memset(f, INF, sizeof(f));
	f[0][0] = 0;
}

void read_case()
{
	init();
	scanf("%d%d", &n, &C);
	for(int i = 1; i <= n; i++) scanf("%d%d", &V1[i], &V2[i]);
}

void dp()
{
	for(int i = 1; i <= n; i++)
	{
		for(int v1 = V1[i]; v1 <= C; v1++)
		{
			for(int v2 = V2[i]; v2 <= C; v2++)
			{
				if(f[v1-V1[i]][v2-V2[i]] != INF)
				{
					f[v1][v2] = min(f[v1][v2], f[v1-V1[i]][v2-V2[i]]+1);
				}
			}
		}
	}
}

void solve()
{
	read_case();
	dp();
	int ans = INF;
	for(int i = 0; i <= C; i++)
	{
		for(int j = 0; j <= C; j++)
		{
			if(i*i + j*j == C*C)
			{	
				ans = min(ans, f[i][j]);
			}
		}
	}
	if(ans != INF) printf("%d\n", ans);
	else printf("not possible\n");
}

int main()
{
	int T;
	scanf("%d", &T);
	while(T--)
	{
		solve();
	}
	return 0;
}


你可能感兴趣的:(UVA 10306 e-Coins)