题意:有m种硬币和目标值s,如果能最少拿k个可以让拿出的硬币的x的和和y的和的平方和等于s的平方,输出k。
题解:完全背包问题,f[i][j]代表当硬币的x和y分别为i和j时最少共有多少个硬币组成,然后遍历一遍f数组选出满足条件的即i^2+j^2=s^2时最小是多少。
#include <stdio.h>
#include <string.h>
const int N = 305;
const int INF = 0x3f3f3f3f;
struct Coin {
int x, y;
}c[N];
int f[N][N], t, m, s, res;
void dp() {
for (int i = 0; i <= s; i++) {
for (int j = 0; j <= s; j++) {
for (int k = 1; k <= m; k++) {
if (i - c[k].x < 0 || j - c[k].y < 0)
continue;
if (f[i][j] > f[i - c[k].x][j - c[k].y] + 1)
f[i][j] = f[i - c[k].x][j - c[k].y] + 1;
}
}
}
res = INF;
for (int i = 0; i <= s; i++)
for (int j = 0; j <= s; j++)
if (i * i + j * j == s * s)
if (res > f[i][j])
res = f[i][j];
}
int main() {
scanf("%d", &t);
while (t--) {
memset(f, INF, sizeof(f));
f[0][0] = 0;
scanf("%d%d", &m, &s);
for (int i = 1; i <= m; i++)
scanf("%d%d", &c[i].x, &c[i].y);
dp();
if (res < INF)
printf("%d\n", res);
else
printf("not possible\n");
}
return 0;
}