1. 程式人生 > >多重部分和問題 DP

多重部分和問題 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 -