(複習)poj 1742 coins 多重揹包可達性問題

Coins
Time Limit: 3000MS   Memory Limit: 30000K
Total Submissions: 28958   Accepted: 9828

Description

People in Silverland use coins.They have coins of value A1,A2,A3...An Silverland dollar.One day Tony opened his money-box and found there were some coins.He decided to buy a very nice watch in a nearby shop. He wanted to pay the exact price(without change) and he known the price would not more than m.But he didn't know the exact price of the watch. 
You are to write a program which reads n,m,A1,A2,A3...An and C1,C2,C3...Cn corresponding to the number of Tony's coins of value A1,A2,A3...An then calculate how many prices(form 1 to m) Tony can pay use these coins. 

Input

The input contains several test cases. The first line of each test case contains two integers n(1<=n<=100),m(m<=100000).The second line contains 2n integers, denoting A1,A2,A3...An,C1,C2,C3...Cn (1<=Ai<=100000,1<=Ci<=1000). The last test case is followed by two zeros.

Output

For each test case output the answer on a single line.

Sample Input

3 10
1 2 4 2 1 1
2 5
1 4 2 1
0 0

Sample Output

8
4

Source



題目大意:

有n種面額的硬幣,分別爲a[i],每種硬幣一共有c[i]個。問可以構造出多少不同的價格。


總結&反思:

這道題做得實在是沒有思路,

總的來說是————

沒有真正理解好多重揹包問題一維dp的多態疊加性質,而這是因爲平時沒有主動使用一維dp造成的。

並且,老是被自己的固有思維限制住,總是想用“二進制優化”以及“隊列優化”


這道題有兩個閃光點,第一個就是多態疊加的應用,第二個就是下面代碼中num數組的使用

而多態疊加這個性質或者說真正理解一維dp正是這道題的突破關鍵點,第一個問題解決了,相信我肯定可以解決出第二個問題。


解題思路:

(1)對於每一種商品(硬幣),從1到m便利一遍所有價格,如果j-a[i]是可構造的,那麼jj就是可構造的,所以我們用dp來表示是否可構造。

(2)因爲每種商品有多個,j-a[i]可以是之前不同商品的疊加,也可以是當前商品若干個疊加的結果,對於前者沒有限制。而對於後者,使用當前商品的

個數必須小於當前商品的最大個數(且這個數值只在當前的i的時候使用,過時就無用了),那麼我們就可以用一個數組num來記錄當前這個價格是當前商品的幾次疊加

每進入一個新的i時就歸零一次。




下面是ac代碼:

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <memory.h>
#include <string>
#include <vector>
#include <list>
#include <map>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <numeric>
#include <functional>
#define maxn 1000005

using namespace std;
bool dp[100002];
int num[100002];
int a[102];
int c[102];
int n,m;

int main()
{
    while(scanf("%d%d",&n,&m)!=EOF){
        if(!n&&!m) return 0;
        int res=0;
        memset(dp,false,sizeof(dp));
        memset(num,0,sizeof(num));
        for(int i=1;i<=n;i+=1){
            scanf("%d",&a[i]);
        }
        for(int i=1;i<=n;i+=1){
            scanf("%d",&c[i]);
        }

        dp[0]=true;
        for(int i=1;i<=n;i+=1){
            memset(num,0,sizeof(num));
            for(int j=a[i];j<=m;j+=1){
                if(dp[j-a[i]]&&!dp[j]&&num[j-a[i]]<c[i]){
                    dp[j]=true;
                    res+=1;
                    num[j]=num[j-a[i]]+1;
                }
            }
        }
        printf("%d\n",res);
    }

    return 0;
}







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