uva 10306 - e-Coins(完全背包)

题目链接:10306 - e-Coins


题目大意:给出m和s, 再给出m种电子硬币,每种硬币有两种金额xi,yi。现在要在m种硬币种选若干个硬币,可以重复选同一种硬币, 使得(x1 + x2 + .... + xn) ^ 2 + (y1 + y2 + ... + yn) ^ 2 == s * s, 要求n尽量小,(n为选取硬币的个数), 如果不能选出满足条件的硬币,输出-1。


解题思路:二维的完全背包问题,注意要用long long。


 

#include <stdio.h>

#include <string.h>

const int N = 305;



struct coin{

    int x;

    int y;

}val[50];

int n, s, S, dp[N][N];



void read() {

   memset(val, 0, sizeof(val));

   scanf("%d%d", &n, &s);

   S = s * s;

   for (int i = 0; i < n; i++)

       scanf("%d%d", &val[i].x, &val[i].y);

}



int solve() {

    int cnt = 1 << 30;

    memset(dp, 0, sizeof(dp));

    dp[0][0] = 1;

    for (int k = 0; k < n; k++) {

	for (int i = 0; i <= s; i++) {

	    for (int j = 0; j <= s; j++) {

		if (dp[i][j]) {

		    int p = i + val[k].x, q = j + val[k].y;

		    if (p > s || q > s) break;

		    if (dp[p][q] == 0 || dp[i][j] + 1 < dp[p][q])

			dp[p][q] = dp[i][j] + 1;

		    if (p * p + q * q == S && dp[p][q] < cnt)

			cnt = dp[p][q];

		}

	    }

	}

    }

    if (cnt == 1 << 30) return 0;

    else return cnt;

}



int main() {

    int cas;

    scanf("%d", &cas);

    while (cas--) {

	read();

	int ans = solve();

	if (ans)

	    printf("%d\n", ans - 1);

	else

	    printf("not possible\n");

    }

    return 0;

}


 

 

你可能感兴趣的:(uva)