DP DAG 9-3硬幣問題(演算法競賽入門經典p162)
有n種硬幣,面值分別為V1,V2,V3,.....Vn,每種都有無限多。給定非負整數S,可以選用多少個硬幣,使得面值之和恰好為S?輸出硬幣數目的最小值和最大值。1<=n>=100,
0<=S<=10000,1<=Vi<=S.
思路:本題是固定終點和起點的DAG動態規劃。我們把每種面值看做一個點,表示“還需要湊足的面值”,則初始狀態為S,目標狀態為0。如當前在狀態i,沒使用一個硬幣j,狀態變轉移到i-Vj。
我對於這道題目的意義就是想討論一下書上所說的三種DP方式和路徑輸出方式,因為書上沒有給出完整的程式碼,我覺得整理一下,對DAG上DP的學習非常有幫助。
第一:遞推法。
第二種:遞推法,但是路勁已經優化,用一個min_coin[],max_coin[]來表示“面值還差i時”的面值種類j.雖然我現在還在痛苦的學習DP中,也談不上什麼經驗,但是我非常喜歡這種方法。#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> using namespace std; const int maxn=10000; const int inf=1000000000; int n,S; int Min[maxn],Max[maxn],V[maxn]; void print_ans(int *dp,int S) { for(int i=1;i<=n;i++) { if(S>=V[i]&&dp[S]==dp[S-V[i]+1]) { printf("%d\n", i); print_ans(dp,S-V[i]); break; } } } int main() { int i,j; while(scanf("%d%d",&n,&S)==2) { memset(Min,0,sizeof(Min)); memset(Max,0,sizeof(Max)); memset(V,0,sizeof(V)); for(i=1;i<=n;i++) scanf("%d",&V[i]); for(i=1;i<=n;i++) Min[i]=inf,Max[i]=-inf; Min[0]=Max[0]=0; for(i=1;i<=S;i++) { for(j=1;j<=n;j++) { if(i>=V[j]) { Min[i]=min(Min[i],Min[i-V[j]]+1); Max[i]=max(Max[i],Max[i-V[j]]+1); } } } } return 0; }
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> using namespace std; const int maxn=10000; const int inf=1000000000; int Min[maxn],Max[maxn],min_coin[maxn],max_coin[maxn]; int V[maxn]; int n,S; void print(int *dp_path,int S) { while(S) { printf("%d",dp_path[S]); S-=V[dp_path[S]]; } } int main() { int i,j; scanf("%d%d",&n,&S); for(i=1;i<=n;i++) scanf("%d",&V[i]); Min[0]=Max[0]=0; for(i=1;i<=n;i++) Min[i]=inf,Max[i]=-inf; for(i=1;i<=S;i++) { for(j=1;j<=n;j++) { if(i>=V[j]) { if(Min[i]>Min[i-V[j]]+1) { Min[i]=Min[i-V[j]+1]; min_coin[i]=j; } if(Max[i]<Max[i-V[j]]+1) { Max[i]=Max[i-V[j]]+1; max_coin[i]=j; } } } } print(min_coin,S); printf("\n"); print(max_coin,S); printf("\n"); return 0; } 第三種:記憶搜尋,要搜尋兩次。。。待續,回到寢室在寫
相關推薦
DP DAG 9-3硬幣問題(演算法競賽入門經典p162)
有n種硬幣,面值分別為V1,V2,V3,.....Vn,每種都有無限多。給定非負整數S,可以選用多少個硬幣,使得面值之和恰好為S?輸出硬幣數目的最小值和最大值。1<=n>=100, 0<=S<=10000,1<=Vi<=S. 思路:本題是
使用檔案進行輸入輸出的兩種方式(演算法競賽入門經典第2章)
使用檔案進行輸入輸出的兩種方式: 1, 重定向 freopen("input.txt", "r", stdin); freopen("output.txt", "w", stdout); 上述語句將使得scanf從檔案input.
ACM準備之路(演算法競賽入門經典1)排列
問題:1~9,組成三個三位數,abc、def,ghi,每個數字用且只用一次,使三個數為1:2:3,每行一個解。這是書上2-6,由於當時想的方法太麻煩,然後去網上找了大佬的一篇文章,具體是哪位的不太記得了,在此說聲謝謝,確實想的比我的簡單多了。 ps:良品鋪子的芒果乾不錯
演算法競賽入門經典(第二版)第三章陣列和字串習題3-4週期串
如果一個字串可以由某個長度為k的字串重複多次得到,則稱該串以k為週期。例如abcabcabc以3為週期(注意,它也以6和12為週期)。輸入一個長度不超過80的字串,輸出其最小週期 #include<stdio.h> int main() { char a[100];
演算法競賽入門經典(第二版)第三章陣列和字串習題3-3數數字
把前n(n<=10000)個整數順次解除安裝一起:123456789101112…數一數0~9各出現多少次(輸出10個整數,分別是0,1,…,9出現的次數) #include<stdio.h> #define N 100000 char s[N],temp[10]; i
演算法競賽入門經典(第二版)第三章陣列和字串習題3-2分子量
給出一種物質的分子式不帶括號,求分子量。本題中的分子式只包含4種原子分別為CHON,原子量分別為12.01,1.008,16.00,14.01(單位g/mol)。例如,C6H5OH的分子量是94.108g/mol #include <stdio.h> int main() {
演算法競賽入門經典(第二版)第三章陣列和字串習題3-1得分
給出一個由O和X組成的串(長度1-80)統計得分。每個O的得分為目前連續出現的O的個數,X的得分為0。 #include <stdio.h> int main() { int b=0,c=0; int j=1; char a[80]; scan
演算法競賽入門經典(第二版)第三章陣列和字串中競賽題目例題3-5 生成元
如果x加上x的各個數字之和得到y,就說x是y的生成元。給出n(1<=n<=100000)求最小生成元。無解輸出0.例如n=216時的解為198 分析 本題看起來是個數學題實則不然。假設所求生成元為m不難發現m<n.換句話說只需列舉所有的m<n看看有沒有哪個數是n的
演算法競賽入門經典(第二版)第三章陣列和字串中競賽題目例題3-4猜數字
實現一個經典猜數字遊戲。給定答案序列和使用者猜的序列,統計有多少數字位置正確A,有多少數字在兩個序列都出現過但位置不對B 輸入包含多組資料。每組第一行為序列長度為n,第二行是答案序列,接下來是若干猜測序列。猜測序列全0時該組資料結束。n=0時輸入結束 [分析] 直接統計可得A,為
演算法競賽入門經典(第二版)第三章陣列和字串中競賽題目選講例題3-3迴文詞
輸入一個字串,判斷它是否為迴文串以及映象串。輸入字串保證不含數字0。所謂迴文串,就是反轉以後和原串相同,如abba和madam。所有映象串,就是左右映象之後和原串相同,如2S和3AIAE。注意,並不是每個字元在映象之後都能得到一個合法字元。在本題中,每個字元的映象如圖3-3所示(空白
演算法競賽入門經典(第二版)第三章陣列和字串中競賽題目選講例題3-2WERTYU
把手放在鍵盤上時,稍不注意就會往右錯一位。這樣,輸入Q會變成輸入W,輸入J會變成輸入K等。 輸入一個錯位後敲出的字串(所有字母均為大寫),輸出打字員本來想打出的句子。輸入保證合法,即一定是錯位之後的字串。例如輸入中不會出現大寫字母A。 #include<stdio.h> ch
《演算法競賽入門經典》 習題3-9 子序列
《演算法競賽入門經典》 習題3-9 子序列 輸入兩個字串s和t,判斷是否可以從t中刪除0個或多個字元(其他字元順序不變),得到字串s。例如,abcde可以得到bce,但無法得到dc。 #include<stdio.h> #include<string.h> i
演算法競賽入門經典(第二版) 習題3-5 謎題(Puzzle) UVa227 Finals1993
Page 57 Description 一個5*5的網格中恰好有一個格子是空的,其他格子各有一個字母,四條指令A,B,L,R分別表示將空格上、下、左、右移動。輸入初始網格(以Z結束)和一串指令(以0結束),輸出執行操作後的網格。越界則輸出“This puzzle has n
演算法競賽入門經典(第2版)習題4-3 黑白棋 Othello UVa220
這題邏輯和習題4-1象棋很相似,沒什麼特別的。 第一次提交報wa,添加了若干樣例測試,發現邏輯無誤。 與樣例輸出對拍後發現輸出尾部多了一個換行符,修改後ac。 //#define LOCAL //#define TESTING #include<stdio.h>
演算法競賽入門經典(第2版)習題3-4 週期串 Periodic Strings UVa445
這題把我虐哭了。 提交了13次才ac。 演算法本身沒什麼好說的,UVa上html版和pdf版的輸入輸出格式要求不一樣,以html版為準。 而且html版的輸入輸出格式都有點奇葩,不認真看原文細節是ac不了的。 參考了他的例程,我才找到問題的解決辦法。 UVa評測系統中的空
演算法競賽入門經典(第二版) 習題3-11 換低檔裝置(Kickdown) UVa1588 NEERC2006
Page 59 題意:給出兩個長度分別為n1,n2且每列高度只為1或者2的長條,需要將它們放入一個高度為3的容器,問容器的最短長度。 思路:兩個字串起始端對齊,分兩個方向移動,得到兩個最短長度,再取較
演算法競賽入門經典 習題2-3 韓信點兵(hanxin)
習題2-3 韓信點兵(hanxin) 相傳韓信才智過人,從不直接清點自己軍隊的人數,只要讓士兵先後以三人一排、五人一排、七人一排地變換隊形,而他每次只掠一樣隊伍的排尾就知道總人數了。輸入3個非負整數a,b,c,表示每種隊形排尾的人數(a<3,b<5
演算法競賽入門經典(第2版)習題3-5 謎題(Puzzle) Uva227
C++編寫 #include<iostream> using namespace std; int main() { int x = 2, y = 1; char Pu
UVa220 演算法競賽入門經典(第2版)習題4-3 黑白棋 Othello
老規則 題目解釋看他們的 程式碼看我的。。 可能我的程式碼略微濃縮一些。 。。 。。我找了半天,,程式碼寫的都好長。,要是看懂了題目的話 就看我的程式碼吧。 http://blog.csdn.net/kyoma/article/details/51
演算法競賽入門經典:習題3-8 手機鍵盤(keyboard)
輸入一個由小寫字母組成的英文單詞,輸出用手機的預設英文輸入法的敲鍵序列。例如要打出pig這個單詞,需要按1次p,3次i,(稍作停頓後)1次g,記為p1i3g1。 #include<stdio.h> #include<string.h> #define