POJ 1742(Coins)

题目链接:http://poj.org/problem?id=1742

与一般的背包问题不一样,这是要计算满足条件的情况的数量,而不是计算最值,一开始的思路就是按照书上的类比:

dp[i][j] := 用前i种硬币能否凑成j

递推:dp[i][j] = (dp[i – 1][j – k * A[i]])为真的时候

但是 MLE,其实一点都不惊讶吧,数组开那么大肯定会出问题呀,所以只能放弃二维数组:

dp[j] := 在第i次循环时之前表示用前 i-1 种硬币凑成 j 时第 i 种硬币最多能剩余多少个(-1表示配不出来),循环之后就表示第i次的状态

ac代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <iostream>
 5 #define MAX_N 101
 6 using namespace std;
 7 int n,m;
 8 int a[MAX_N],c[MAX_N];
 9 int dp[100005];
10 
11 void solve(){
12     memset(dp,-1,sizeof(dp));
13     dp[0]=0;
14     for(int i=0;i<n;i++){
15         for(int j=0;j<=m;j++){
16             if(dp[j]>=0)
17                 dp[j]=c[i];
18             else if(j<a[i]||dp[j-a[i]]<=0)
19                 dp[j]=-1;
20             else
21                 dp[j]=dp[j-a[i]]-1;
22         }
23     }
24     int ans=0;
25     for(int i=1;i<=m;i++)
26         if(dp[i]>=0)    ans++;
27     printf("%d\n",ans);
28 }
29 
30 int main(void){
31     while(scanf("%d%d",&n,&m)&&(n||m)){
32         for(int i=0;i<n;i++)    scanf("%d",&a[i]);
33         for(int j=0;j<n;j++)    scanf("%d",&c[j]);
34         solve();
35     }
36 
37     return 0;
38 }
View Code

猜你喜欢

转载自www.cnblogs.com/jaszzz/p/12636750.html