您的位置:首页 > 其它

Beef McNuggets

2013-11-09 11:22 246 查看
题意:给定N种金额的货币,求最大的不能拼成的金额,如果这个金额不存在或者为无限大则输出0

解题思路

设货币金额的集合为S,f[i] = 0代表金额为i不能组成,f[i] = 1代表金额能够组成
DP问题,滚雪球的过程:如果f[i] = 1,则f[i + S[j]] = 1,其中j取[1, N]
DP的上限为最大两个数的最小公倍数,证明可参见NOCOW(http://www.nocow.cn/index.php/USACO/nuggets)问题分析这一小节
无限解的情况,存在于这N个数的最大公倍数不为1的情况下,这样一来不能被这个最大公倍数整除的数就构造不出来,这样的数是无限大的
如果从[1, 最小公倍数]都能构造出来,则无解
代码

/*
ID: zc.rene1
LANG: C
PROG: nuggets
*/

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int GetGCD(int a, int b)
{
int temp;
if (a < b)
{
temp = a;
a = b;
b = temp;
}

while (a * b != 0)
{
a = a % b;
temp = a;
a = b;
b = temp;
}

return a;
}

int main(void)
{
FILE *fin, *fout;
int N, i, j, max = -1, end, gcd;
int seq[10];
int *f = NULL;

fin = fopen("nuggets.in", "r");
fout = fopen("nuggets.out", "w");

fscanf(fin, "%d", &N);

for (i=0; i<N; i++)
{
fscanf(fin, "%d", &seq[i]);
if (seq[i] > max)
{
max = seq[i];
}
}

gcd = seq[0];
for (i=1; i<N; i++)
{
gcd = GetGCD(gcd, seq[i]);
}
if (gcd != 1)
{
fprintf(fout, "0\n");
return 0;
}

end = max * max;

f = (int *)malloc(end * sizeof(int));
memset(f, 0, end * sizeof(int));

f[0] = 1;

for (i=0; i<end; i++)
{
if (f[i] == 0)
{
continue;
}
for (j=0; j<N; j++)
{
if (i + seq[j] < end)
{
f[i + seq[j]] = 1;
}
}
}

for (i=end-1; i>0; i--)
{
if (f[i] == 0)
{
break;
}
}

fprintf(fout, "%d\n", i);

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: