完全揹包輸出方案數(dp)
阿新 • • 發佈:2020-10-04
在一個10美元的商店裡,所有東西都值10美元或更少。為了在出納處更有效地為客戶服務,需要以最少數量的硬幣進行找零。
在這個問題中,您將使用不同的硬幣提供給定的找零值。編寫一個程式來計算每種硬幣型別所需的硬幣數量。
輸入包括值v,硬幣組n的大小以及每個硬幣的面值f1,f2,...,fn。輸出是數字列表,即c1,...,cn,表示每種硬幣型別所需的硬幣數量。更改可能有很多方法。 v值是一個滿足0 <v≤2000的整數,表示所需的更改
分。硬幣的面值小於或等於10000。程式的輸出應採用所需硬幣數量最少的組合。
例如,由香港金融管理局發行的香港硬幣包括10美分,20美分,50美分,1美元,2美元,5美元和10美元,在輸入中表示為n = 7,f1 = 10 ,f2 = 20,f3 = 50,f4 = 100,f5 = 200,f6 = 500,f7 = 1000。
輸入
測試資料可能包含許多測試用例,請處理到檔案末尾。
每個測試用例的一行中都包含整數v,n,f1,...,fn。保證n≤10且0 <f1 <f2 <... <fn。
輸出
輸出是一行中的n個數字,以空格分隔。如果沒有可能的更改,則您的輸出應為單個-1。如果可能的解決方案不止一種,則您的程式應輸出使用更多面值較低的硬幣的解決方案。
樣例輸入
2000 7 10 20 50100200500 1000
250 4 10 20 125150
35 4 10 20 125 150
48 4 1 8 16 20
40 4 1 10 13 37
43 5 1 2 21 40 80
樣例輸出複製
0 0 0 0 0 0 2
0 0 2 0
-1
0 1 0 2
3 0 0 1
1 1 0 1 0
#pragma GCC optimize(1) #pragma GCC optimize(2) #pragma GCC optimize(3,"Ofast","inline") #include<cstring> #include<cstdio> #include<iostream> #include<queue> #include<algorithm> using namespace std; typedef long long ll; template <typename Tp> void read(Tp &x){//read(n); x=0;char ch=1;int fh; while(ch!='-'&&(ch>'9'||ch<'0')){ ch=getchar(); } if(ch=='-'){ fh=-1;ch=getchar(); }else fh=1; while(ch>='0'&&ch<='9'){ x=(x<<1)+(x<<3)+ch-'0';ch=getchar(); } x*=fh; } inline charread1()//字串讀入掛 { register char ch=getchar(); while(ch<'A'||ch>'M')ch=getchar(); return ch; } const int maxn=1e6+100; const int mod=1000000007; const int INF=0x3f3f3f; int a[maxn]; int dp[maxn]; int vis[maxn]; int main(){ int m,n; while(cin>>m>>n){ memset(dp,0x3f3f,sizeof(dp)); memset(vis,0,sizeof(vis)); for(int i=1;i<=n;i++){ cin>>a[i]; } dp[0]=0; for(int i=1;i<=n;i++){ for(int j=a[i];j<=m;j++){ dp[j]=min(dp[j],dp[j-a[i]]+1); } } if(dp[m]==0x3f3f3f3f){ printf("-1\n"); continue; } int z=m; int p=0; for(int i=n;i>=1;i--){ p=0; while(z-a[i]>=0&&dp[z]==dp[z-a[i]]+1){ vis[i]++; z-=a[i]; } } for(int i=1;i<=n;i++){ cout<<vis[i]<<" "; } cout<<endl; } }