(noip 模擬 gift)

Problem

Gift
【問題描述】
人生贏家老王在網上認識了一個妹紙,然後妹紙的生日到了,爲了表示自己的心意,他決定送她禮物。可是她喜愛的東西特別多,然而他的錢數有限,因此他想知道當他花一定錢數後剩餘錢數無法再購買任何一件剩餘物品(每種物品他最多買一個)時有多少種方案,兩種方案不同,當且僅當兩種方案中至少有一件品不同,可是由於他忙着準備泡下一個妹紙(chi),因此麻煩聰明的你幫幫忙。

【輸入格式】
輸入第一行n和m,n表示妹紙喜歡的禮物數目,m表示現有的錢數,第二行n個數,表示n個物品的價格。

【輸出格式】
輸出一行一個數表示方案數目,答案對1000000007取模。

【樣例輸入1】
gift.in
6 25
8 9 8 7 16 5
【樣例輸出1】
gift.out
15
【數據範圍】
30%的數據: 0<=n<=100 0<=m<=500
100%的數據:0<=n<=1000 0<=m<=1000
注意:所有物品價格均小於m

Solution

  • 這個題最重要的是理解f[][]的含義:f[i][j]表示對n~i的物品做揹包之後,剩餘容量爲j的方案數
  • 那麼首先對物品的價格從小到大排序,排序的目的放在後面
  • s[i]表示從1到i的前綴和
  • DP是倒着循環的,從價格高的物品開始,即f[i][j]+=f[i+1][j+v[i]] ,初值爲f[n+1][m]=1 ,具體意義和01揹包相同
  • 更新答案的時候,可以假設前i-1種物品一共花費了X=i1k=1ak 元,分配給前i-1種物品的容量爲X時的方案數一定爲1,而求的是買不到時的方案數,因此分配給第i個物品的錢數c應該滿足0<=c<ai (注意是”<=”和”<”)。根據乘法原理,剩餘j的容量時,買不到第i個物品的方案數應該爲1×f[i+1][j] ,而j的範圍是s[i1]<=j<s[i] (同樣注意是”<=”和”<”),當然s[i]>m的情況特殊判斷一下

Code

// by spli
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<iostream>
#define LL long long
using namespace std;

const int N=1010;
const int mod=1e9+7;
int n,m;
int a[N];
LL s[N];
LL f[N][N];
LL ans;

int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;++i) scanf("%d",&a[i]);
    sort(a+1,a+1+n);
    for(int i=1;i<=n;++i) s[i]=s[i-1]+a[i];
    if(s[n]<m){     //特判
        cout<<1;return 0;
    }
    f[n+1][m]=1;
    for(int i=n;i>=1;--i){
        int k=min((LL)m+1,s[i]);
        for(int j=s[i-1];j<k;++j) (ans+=f[i+1][j])%=mod;
        for(int j=m;j>=0;--j){
            if(j+a[i]<=m) (f[i][j]+=f[i+1][j+a[i]])%=mod;
            f[i][j]+=f[i+1][j];
        }
    }
    cout<<ans;
    return 0;
}




/*
100 500
93 394 335 69 393 420 148 389 
126 435 42 51 266 256 290 136 
301 41 120 110 475 178 500 240 
409 66 212 499 442 27 372 456 
328 372 210 20 227 142 274 468 
185 337 20 164 382 321 481 182 
218 292 216 155 293 462 322 398 
239 94 188 384 184 270 199 223 
77 454 363 197 152 165 1 431 
308 166 19 403 97 213 350 306 
318 428 310 478 251 383 27 
264 489 193 152 165 268 53 
323 79 69 221 480 277 
*/

// 答案爲318465
發佈了80 篇原創文章 · 獲贊 10 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章