poj-1712 Coins(多重リュックサック最適化)

2946 ワード

テーマリンク:http://poj.org/problem?id=1742
Coins
Time Limit: 3000 MS
 
メモリLimit: 30000 K
Total Submissions: 33242
 
Acceepted: 11283
Description
People in Silverland use coins.They have coins of value A 1,A 2,A 3…An Silverland dollar.One day Tony opened his money-box and found there were some coins.He decided to buy a very nitwatby shop.He want to pay t he exact price(without change)and the the the prexout 
You are to write a program which reads n,m,A 1,A 2,A 3…An and C 1,C 2,C 3…Cn corelding to the number of Tony coins A 1,A 2,A 3…An then cacaculate how many press(form 1 to to to to to to to to to to Tonypanese)cany.cars Coinse。 
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 2 n integers、denoting A 1、A 2、A 3=Andres=C 1
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
題意n種のコインで、目標のお金はmです。各硬貨は数と価値をあげます。1~mまでにどれぐらいのお金が組めますか?
考え方:楼教主「男8題」の一つで、この問題は簡単そうですが、データは非常に変態です。悪いのは基本的にTLEです。二進法の多重リュックサックは過ぎられません。単調な列の最適化の多重リュックサックも過ぎられません。混合リュックサックの単調な行列を加えてカードを使ったのです。自分が弱すぎるとしか言えません。単調な列に対する理解が足りない。
コード:
ヒドイincludeヒドイincludeヒドイイinclude嗳嗳includeusing namespace std;define M 100010萶define N 110 int dp[M]int b[M]int l,rint n,m;int s[N],flags[M];int main(){    int num、sum    while(~scanf('%d%d"、&n,&m)&(n+m)    {         for(int i=1;i<=n;i++)            scanf("%d"、&s[i])        for(int i=1;i<=m;i++)            dp[i]=0        dp[0]=1        for(int i=1;i<=n;i++)        {             scanf("%d"、&num);            int v=s[i]            if(num==1)            {                 for(int j=m)j>=v;j--)                    if(dp[j]&dp[j-v]                        dp[j]=1            }             else if(num*v>=m)            {                  for(int j=vj<=m;j++)                    if(dp[j]&dp[j-v]                        dp[j]=1            }             else            {                 for(int d=0dnum)                        sum-=b[l+];                        b[+r]=dp[j];                        sum+=dp[j];                        if(dp[j]&sum)                            dp[j]=1                    }                 }             }         }         int t=0        for(int i=1;i<=m;i++)            if(dp[i])            t++;        printf(「%d」、t)    }     return 0;