hdu 1709 求天平不能稱重的重量 動態規劃
給定一個天平和n個砝碼,每個砝碼都有一個重量,求出從1到這些砝碼的總和之間不能被天平表示的重量。天平可以兩端放砝碼。
動態規劃做法,看網上都是母函式,真心不懂。。
dp[i]如果是0表示這些砝碼不能稱重i重量,如果是1表示能稱重i重量。
對於每個砝碼,假設當前砝碼重量是b[i],那麼j從最大值開始,減小到b[i],
如果存在一個dp[j-b[i]]為1,說明當前的j能被組成。
j逆著迴圈的原因是由於每個砝碼只有 一個,類似於01揹包與完全揹包的樣子,
如果正向迴圈會導致每個物品可能使用多次,逆向迴圈則不會出現這個問題。
其實舉個例子就能看出來了。
因為天平是可以兩邊放的,因此可以從大的數中減去小的數,方法就是對於每個砝碼重量b[i],
遍歷在dp陣列中為真的並且比b[i]那些j,那麼dp[j-b[i]]也一定為真,這個乍一看不靠譜,但經過分析好像是對的。
如果b[i]被重複使用了怎麼辦?即dp[j]已經使用了b[i]了,你還要減去b[i],但它只有一個啊。
此時如果dp[j]已經使用了b[i],那麼dp[j-b[i]]早已經為真了,即由別的砝碼早可以組成dp[j-b[i]]了。
如果是多個砝碼減2個砝碼怎麼辦?不會漏掉嗎?其實在第一個砝碼的時候就記錄了多個砝碼減第一個砝碼的結果,
到第二個砝碼的時候會用到這個結果。這樣就不會漏了。
其實這也是dp,這個dp的j要正向進行,逆向進行就會導致砝碼重複使用。
#include<bitset> #include<map> #include<vector> #include<cstdio> #include<iostream> #include<cstring> #include<string> #include<algorithm> #include<cmath> #include<stack> #include<queue> #include<set> #define inf 0x3f3f3f3f #define mem(a,x) memset(a,x,sizeof(a)) using namespace std; typedef long long ll; typedef pair<int,int> pii; inline int in() { int res=0; char c; while((c=getchar())<'0' || c>'9'); while(c>='0' && c<='9')res=res*10+c-'0',c=getchar(); return res; } const int N=100006; int dp[N]; //注意要大一些, 因為範圍是砝碼的總和 int b[2006]; int ans[20000]; int main() { int n; while(~scanf("%d",&n)) { mem(dp,0); int mx=0; for(int i=0;i<n;i++) { b[i]=in(); mx+=b[i]; } dp[0]=1; for(int i=0;i<n;i++) { for(int j=mx;j>=b[i];j--) { if(dp[j-b[i]]) dp[j]=1; } } for(int i=0;i<n;i++) { for(int j=b[i];j<=mx;j++) { if(dp[j])dp[j-b[i]]=1; //每個比當前砝碼大的,減去當前砝碼的重量。 } } int p=0; for(int i=1;i<=mx;i++)if(!dp[i])ans[p++]=i; printf("%d\n",p); for(int i=0;i<p-1;i++) { printf("%d ",ans[i]); } if(p>0)printf("%d\n",ans[p-1]); //當時又漏了p>0 } return 0; }
相關推薦
hdu 1709 求天平不能稱重的重量 動態規劃
給定一個天平和n個砝碼,每個砝碼都有一個重量,求出從1到這些砝碼的總和之間不能被天平表示的重量。天平可以兩端放砝碼。 動態規劃做法,看網上都是母函式,真心不懂。。 dp[i]如果是0表示這些砝碼不能稱重i重量,如果是1表示能稱重i重量。 對於每個砝碼,假設當前砝碼重量是b
砝碼稱重 5個砝碼 用天平稱重時,我們希望用盡可能少的砝碼組合稱出儘可能多的重量。
/*砝碼稱重 5個砝碼 用天平稱重時,我們希望用盡可能少的砝碼組合稱出儘可能多的重量。 如果只有5個砝碼,重量分別是1,3,9,27,81。則它們可以組合稱出1到121之間任意整數重量(砝碼允許放在左
使用天平稱重,經驗證,用四個砝碼可以秤出1~40的全部整數重量,請問是哪四個砝碼?
這個在數學上叫做梅氏砝碼問題,其敘述如下: 若有n個砝碼,重量分別為M1,M2,……,Mn,且能稱出從1到(M1+M2+……+Mn)的所有重量,則再加一個砝碼,重量為Mn+1=(M1+M2+……+M
枚舉 天平稱重
font strong 所有 rst 輸出 color iostream algorithm pan 天平稱重 【問題描述】 用天平稱重時,我們希望用盡可能少的砝碼組合稱出盡可能多的重量。 如果只有5個砝碼,重量分別是1,3,9,27,81 則它們可以組合稱出1
【數學】天平稱重
用天平稱重時,我們希望用盡可能少的砝碼組合稱出儘可能多的重量。如果只有5個砝碼,重量分別是1,3,9,27,81則它們可以組合稱出1到121之間任意整數重量(砝碼允許放在左右兩個盤中)。本題目要求程式設計實現:對使用者給定的重量,給出砝碼組合方案。例如:使用者輸入:5程式輸出
巧用三進位制解決天平稱重問題
1.問題描述: 用天平稱重時,我們希望用盡可能少的砝碼組合稱出儘可能多的重量。 如果有無限個砝碼,但它們的重量分別是1,3,9,27,81,……等3的指數冪 神奇之處在於用它們的組合可以稱出任意整數重量(砝碼允許放在左右兩個盤中)。 本題目要求程式設計實現:對使用者給
【進位制轉換】天平稱重
用天平稱重時,我們希望用盡可能少的砝碼組合稱出儘可能多的重量。如果只有5個砝碼,重量分別是1,3,9,27,81則它們可以組合稱出1到121之間任意整數重量(砝碼允許放在左右兩個盤中)。本題目要求程式設計實現:對使用者給定的重量,給出砝碼組合方案。例如:使用者輸入:5程式輸出
筆試面試題 —— 天平稱重與二進位制
有人曾問帳前卒一道題:至少需要多少個砝碼,才能稱出1~50g物體?這道題有兩個變種: 1.至少需要多少砝碼(左物右碼),才能稱出1~50g物體?2.至少需要多少砝碼(砝碼可以放在任意一邊),才能稱出1~50g物體?第一問可以變為: 至少多少個數字相加,可以表示1~50之間的任
hdu-1231 連續最大子序列(動態規劃)
得到 繼續 用例 using 規劃 mem 空格 編寫 序號 Time limit1000 ms Memory limit32768 kB 給定K個整數的序列{ N1, N2, ..., NK },其任意連續子序列可表示為{ Ni, Ni+1, ..., Nj },其中
Dijkstra演算法,求最短路(dp 動態規劃)
•迪傑斯特拉(Dijkstra)演算法思想 按路徑長度遞增次序產生最短路徑演算法: 把V分成兩組: (1)S:已求出最短路徑的頂點的集合 (2)V-S=T:尚未確定最短路徑的頂點集合 將T中頂點按最短路徑遞增的次序加入到S中, 保證:(1)從源點V0到S中各
LeetCode -- Triangle 路徑求最小和( 動態規劃問題)
Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent numbers on the row below. For example, given the foll
POJ 1458/HDU 1159 最長公共子序列 (動態規劃)
題目連結:poj && hdu 程式碼 #include <iostream> #include <cstdio> #include <algo
HDU 6331 Walking Plan(分塊 動態規劃)
題意 給一個 nn 個節點 mm 條邊的有向圖,第 ii 條邊的兩個端點為 ui,viui,vi,邊的長度為 wiwi,qq 次詢問,每次詢問從節點 ss 到 tt 至少走過 kk 條路徑的最小距離。 輸入 第一行包含一個整數 T(1
hdu 1024 Max Sum Plus Plus(動態規劃+m子段和的最大值)
Now I think you have got an AC in Ignatius.L's "Max Sum" problem. To be a brave ACMer, we always challenge ourselves to more difficult problems. Now you ar
101個硬幣100真、1假,真假區別在於重量。請用無砝碼天平稱兩次給出真幣重還是假幣重的結論。
把101個硬幣分成三堆,倆堆50個,和另外一個 一,稱倆堆50個,如果重量相等。 則說明假幣是那單獨的一個 隨便取一個真幣和這個假幣做比較,即可得出哪個硬幣更重 如果重量不相等,說明剩下那個硬幣是真的,然後倆堆50個裡面有一個必然是假的,同時天平不平衡。 用一個
個人小專案:現有12個小球和一個天平,小球中有一個重量與其它的不同,稱重幾次能將這個小球找出來
<script language="JavaScript"> //建立兩個陣列,分別存放左邊盤小球物件和右邊盤小球物件 var leftbar = new Array(); var rightbar = new Array(); //建立一個整形變數,存放當前稱重的次數
HDU acm 1003 Max Sum || 動態規劃求最大子序列和詳解
line namespace num more sequence mem ould 動態規劃 ger Max Sum Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Ot
HDU - 2087 求不可重復字符串的匹配次數
break mar blog cpp cnblogs markdown 重復 字符 body 只要KMP裏對f[i]進行限制即可 /*H E A D*/ int nxt[maxn],f[maxn],ans; char T[maxn],P[maxn]; void buildN
12個球用天平稱3次找到重量不同的那個球
將12個球分成3組,每4個一組 1 將4個A放到天平左邊,4個B放到天平右邊;可能出現2種情況: a:平衡 b:不平衡 1.1 如果是a 情形 說明在天平上的八個球都是普通球,而剩下的4個球裡面有一個是特殊球,我們把不知道的球記為 X ,普通球記為 Y,那麼現在有4個X
動態規劃---砝碼稱重問題
一、演算法分析 動態規劃(Dynamic Programming)這個詞乍一聽感覺甚是高大上,初次學習或者使用的時候會感覺難以理解,這是正常的,畢竟凡事都是一回生二回熟。其實它也不難的,大家要明白一個道理,能寫到課本上給學生學習的東西必然屬於不難的東西,因為太難的東西寫