多重部分和問題 DP
這題是挑戰程式設計競賽上的。
題意:
n個不同的數字,每個有xi個,要恰好組成k這個數是否可能.
如果單純用dp[i][j]表示前i種數,和為j是否可能,那麼轉移方程就是:
dp[i][j]=dp[i][j]||dp[i-1][j-k*a[i]] k=min(j/a[i],x[i])
複雜度為O(n^3)
如果利用多重揹包二進位制的思想把數字按照個數分成其他數字,則可以將複雜度降為O(n^2lg(n))
但是這個題是可以做到O(n^2)的。
具體方法是定義狀態dp[i][j]表示前i種數,和恰好為j時剩餘最多a[i]的數量。也就是說前面我們在推dp[i][j]時,只用到了dp[i-1][k]的值,但是其實在計算q<j 的dp[i][q]時,就已經用到了一些a[i],所以在計算dp[i][j]的時候還是隻使用前面的dp[i-1][k]是低效的,有一些重複計算,那麼我們這樣記錄狀態可以讓轉移方程利用dp[i][q]的值。
狀態轉移
dp[i][j]=x[i];(dp[i-1][j]>0)
dp[i][j]=dp[i][j-a[i]]-1;(dp[i][j-a[i]]>0)
dp[i][j]=-1;(dp[i][j-a[i]]<=0)
看到轉移方程於是可以變為一維。
程式碼。
#include <iostream> #include <cstdio> #include <cstring> using namespace std; const int maxn = 105; const int maxk = 100005; int dp[maxn][maxk]; //dp[i][j]表示前i個數 恰好和為j時 第i個數最多剩多少. int f[maxk]; int main() { freopen("in.txt","r",stdin); int n,a[maxn],x[maxn],k; scanf("%d%d",&n,&k); for(int i=1;i<=n;i++) scanf("%d%d",&a[i],&x[i]); memset(f,-1,sizeof(f)); f[0]=0; for(int i=1;i<=n;i++) for(int j=0;j<=k;j++) { if(f[j]>=0) f[j]=x[i]; else if(j<a[i]||f[j-a[i]]<0) f[j]=-1; else f[j]=f[j-a[i]]-1; } if(f[k]>=0) cout<<"YES\n"; else cout<<"NO\n"; return 0; }
相關推薦
POJ 1742 Coins ( 經典多重部分和問題 && DP || 多重背包 )
count ... mes opened view display 是什麽 [] sizeof 題意 : 有 n 種面額的硬幣,給出各種面額硬幣的數量和和面額數,求最多能搭配出幾種不超過 m 的金額? 分析 : 這題可用多重背包來解,但這裏不討論這種做法。 如果之前有
多重部分和問題(動態規劃(DP))
注:文章內容源自《挑戰程式設計競賽》(第二版) 原題 多重部分和問題 有n種不同大小的數字ai,每種各mi個。判斷是否可以從這些數字之中選出若干使它們的和恰好為K。 1<=n<=100 1<=ai,mi<=100000 1<=K<=100
DP 經典問題(六)多重部分和問題
問題描述: 有n種不同大小的數字ai,每種各mi個,判斷是否可以從這些數字之中選出若干使它們的和恰好為K。(1 <=n <= 100 , 1 <= ai,mi <=100000 , 1 <= K <= 100000) 輸入
多重部分和問題 DP
這題是挑戰程式設計競賽上的。 題意: n個不同的數字,每個有xi個,要恰好組成k這個數是否可能. 如果單純用dp[i][j]表示前i種數,和為j是否可能,那麼轉移方程就是: dp[i][j]=dp[i][j]||dp[i-1][j-k*a[i]] k=min(j/a[i]
063_多重部分和問題(DP)
多重部分和問題:給定一組數,並且給定期中每個數出現的次數,試問是否存在這樣的組合,使其和為一個值K?(某個數可以取多次,但不能超過其次數) 如:a={3,5,8} m={3,2,2} K=17;
[dp]多重部分和問題
多重部分和問題: 有n種不同大小的數字ai,每種各有mi個,判斷是否可以從這些數字中選出若干使它們的和恰好為k。 限制條件: 1 <= n <= 100 1 <= ai,mi <= 100000 a <= K <= 100000 樣例
POJ1742 (dp 多重部分和問題)
題意:要買一個m價錢的東西,現在有一些硬幣,每種硬幣個數和價值不同,求能用這些硬幣在1~m的價格中買到幾種東西。 思路:以dp[j]中j為價格為j的物品,dp[j]的值為第i種硬幣的個數,以此來把
POJ1742 coins 動態規劃之多重部分和問題
變形 價值 span 維數 text 推出 遞推 pro cal 原題鏈接:http://poj.org/problem?id=1742 題目大意:tony現在有n種硬幣,第i種硬幣的面值為A[i],數量為C[i]。現在tony要使用這些硬幣去買一塊價格不超過m的表。他希望
多重部分和問題(多重揹包+二進位制優化)
時間限制: 1 Sec 記憶體限制: 64 MB提交: 18 解決: 14 題目描述 有n種不同大小的數字,每種各個。判斷是否可以從這些數字之中選出若干使它們的和恰好為K。 輸入
挑戰 多重部分和問題
挑戰程式設計P62 多重部分和問題 題意:有n種不同大小的數字,每種數字各mi個。判斷是否可以衝這些數字中選出若干個使他們的和加起來等於K、 有兩種dp方法,但是時間複雜度不一樣 第一種:定義dp
動態規劃之多重部分和問題
分析:拿到這道題目,當然可以用遞迴的形式進行深度搜索遍歷每種情況,但是效率會非常低。一般遞迴帶有前後數值關係的遞迴是可以用動態規劃轉化的,效率會提
練習題 No.10 多重部分和問題
要求 有n種不同大小的數字ai,每種個mi個。判斷是否可以從這些數字之中選出若干使他們的和恰好為K。 限制條件 (1 <= n <= 100) (1 <= ai, mi <
(不易)POJ-1742 多重部分和,多重揹包可行性
題目大意:傳說中的男人八題,是男人就A這八題。有n種面額的硬幣,面額個數分別為A_i、C_i,求最多能搭配出幾種不超過m(1-m)的金額? 分析: ①首先來看看樸素的方法: bool dp[i]
多重小數部分和的漸近式
ant begin -a lan 表示 center hle 好的 big 多重小數部分和的漸近式 最近(6月),我和馬明輝考慮了如下 $k$ 重和式 \begin{equation}\label{eq:1} \sum_{n_1=1}^{N} \sum_{n_2=1}
多重小數部分和的漸近式與小數部分積分(Ⅱ)
本文推廣了多重小數部分和的漸近式與 Ovidiu Furdui 積分問題一文中的結果。 最近,王永強先生推廣 $2$ 重和式的結果,然後我將其推廣到 $k$ 重和式。具體文章將繼續投稿給大學數學雜誌。 對於正整數 $k\geqslant 3$, 正整數 $a_1,\dotsc,
《挑戰程序競賽》 2.1.4 部分和問題
als 按順序 space code log pre std mes namespace 題意:給定整數a1,a2,a3,...,an,判斷是否可以從中選出若幹數,使它們的和恰好為k。 解法:利用dfs深度優先遍歷,從a1開始按順序決定每個數是加還是不加。 code
hdu 1003 Max Sum 最大字段和 dp
題目 int start 今天 end tracking return hdu 簡單 iostream 今天看了一上午dp。看不太懂啊。dp確實不簡單。今天開始學習dp,搜了杭電的dp46道,慢慢來吧。白書上的寫的 又不太具體,先寫幾道題目再說。。。 題目連接:
POJ 1742 Coins 【多重背包DP】
數量 printf can 硬幣 ring editable urn content std 題意:有n種面額的硬幣。面額、個數分別為A_i、C_i,求最多能搭配出幾種不超過m的金額? 思路:dp[j]就是總數為j的價值是否已經有了這種方法,如果現在沒有,那麽我們就一個個硬
【bzoj1531】[POI2005]Bank notes 多重背包dp
can ash cst bit 分組 bsp size 多重 硬幣 題目描述 Byteotian Bit Bank (BBB) 擁有一套先進的貨幣系統,這個系統一共有n種面值的硬幣,面值分別為b1, b2,..., bn. 但是每種硬幣有數量限制,現在我們想要湊出面值k求
51Nod 1050 循環數組最大子段和 | DP
urn F12 int ges href 中間 art space style Input示例 6 -2 11 -4 13 -5 -2 Output示例 20 分析: 有兩種可能,第一種為正常從[1 - n]序列中的最大子字段和;第二種為數組的total_sum -