題目大意:就是有幾種面額的硬幣,輸入錢S,求有多少種不同的找錢方法。S是其中最小面額的倍數。
題目類型: dp / DAG上的路徑計數問題
題目分析:
其實這題跟 UVA 674 - Coin Change 基本一樣。
只是輸入的S是實數,而且輸出的方法數會超過int32(這裡WA了一次) ,所以要 long long。
輸入的S由於是其中最小面額的倍數,所以轉成int,這裡要注意四捨五入(又WA了一次)。
最後,還有輸出int64的時候不要用%I64d(WA T-T...),用%lld。
代碼:
//以5c為單位,面值 2000, 1000, 400, 200, 100, 40, 20, 10, 4, 2, 1<br />// 輸入 S, S=S*100/5;//化整了</p><p>#include<cstdio><br />#include<cstring><br />#include<cmath><br />using namespace std;<br />#define MAXS 6002//300/5*100 = 6000<br />#define int64 long long//答案會超int32②<br />int const n = 11;<br />int64 d[MAXS][n];<br />int vis[MAXS][n];<br />int v[n] = {2000, 1000, 400, 200, 100, 40, 20, 10, 4, 2, 1};//0~10<br />int64 dp(int i, int pre)//還是要設pre是有序, 不然會有 41111 和 14111這類重複。①<br />{<br />if(i==0) return 1;<br />if(vis[i][pre]) return d[i][pre];<br />vis[i][pre] = 1;<br />int64 sum=0;<br />for(int j=pre; j<n; j++)if(i>=v[j])<br />{<br />sum+=dp(i-v[j], j);<br />}<br />return d[i][pre] = sum;<br />}</p><p>int main()<br />{<br />double t;<br />memset(vis, 0, sizeof(vis));//d通用<br />while(scanf("%lf", &t) && t)<br />{<br />//WA的int s = (int)(t*100)/5;//資料 65.10 跑偏。wa③<br />//AC的int s = (int)(floor(t*100+0.5)/5);//要對t進行四捨五入,精確到百分位<br />int s = (int)(t*20+0.5f);//直接對s四捨五入<br />//AC的printf("%6.2lf%17I64d/n", floor(t*100+0.5)/100, dp(s, 0));//%I64d %lld<br />printf("%6.2lf%17lld/n", t, dp(s, 0));//UVA 不能用 %I64d<br />}<br />}