d119
輸入說明 :
有多組測試資料,每組測試資料佔一行,每行會有m個以空白分開的正整數, 若該組測試資料只有0,請不要對此輸出任何數字。
(每行的總金額不會超過50000,且數字可為1,5,10,20,50,100,200,500,1000,2000)
輸出說明 :
對每一組測試資料輸出有多少種用"1,5,10,20,50,100,200,500,1000,2000"所排列的組合(不包含輸入的組合)。
這題是DP的問題,也就是動態規劃, 假設現在要用(1,5,10,)來湊47塊
我們先找不用10元,只用1和5來組成47有幾種可能,
再來找用1個10元,和只用(1,5)元組成37(47-10)元有多少可能,
再來找用2個10元和只用(1,5)元組成27(47-20)有多少可能,
再來找用3個10元和只用(1,5)元組成17(47-30)有多少可能,
再來找用4個10元和只用(1,5)元組成7(47-40)有多少可能,
回來看不用10元,只用1和5來組成47有幾種可能
又分成不用5元,只用1元組成
和用1個5元,其他用1元
和用2個5元,其他用1元.....................
現在有10種硬幣,最大的可能是50000
所以我們開一個2維陣列,紀錄1~50000只用某幾種硬幣的可能性
例如(5,1000)
就是用1,5,10,20,50組成1000的可能性有多少種
要算出每一個的做法就是先把上一層的數字加下來,例如(5,1000),一開始先把(4,1000)的結果加進來,代表不用50,只用1,5,10,20組成1000的可能有多少種,
再來去算
我用1個50,和只用1,5,10,20組成1000的可能有多少 . . . . 做到50能用的數量最多,也就是20個
這個表建完了以後,之後只要查最後一層,就可以了
這題的輸入我是用sscanf來做,sscanf詳細的用法看這篇
#include<stdio.h>
#include<string.h>
#define SIZE 50001
long long int table[10][SIZE] = { 0 };
int main()
{
int dollar[10] = {1,5,10,20,50,100,200,500,1000,2000};
int i,j;
for(i=1;i<SIZE;i++)
table[0][i]=1;
for(i=1;i<10;i++)
for(j=1;j<SIZE;j++)
{
int jtemp=j;
table[i][j]+=table[i-1][j];
while(0<=jtemp)
{
jtemp-=dollar[i];
if(jtemp < 0) break;
if(jtemp==0)
{
table[i][j]+=1;
break;
}
table[i][j]+=table[i-1][jtemp];
}
}
char fake_buffer[1000];
while(gets(fake_buffer))
{
int temp,sum=0;
char *p=fake_buffer;
int l;
while(sscanf(p,"%d%n",&temp,&l)==1)
{
sum+=temp;
p+=l;
}
if(!sum) break;
printf("%lld\n",table[9][sum]-1);
}
return 0;
}