poj1742可套用此模板
题意:有n种不同的数字a[i],每种各b[i]个,判断这些数字可以组成多少个不大于m的数,组成的这些数分别是多少,
判断是否可以组成m。
题解dp[i+1][j]:用前i种数加和得到j时第i种数剩余多少个(不能加和得到i的情况下为-1)
如果前i种数相加能得到 j 的话,第i个数可以留下b[i]个,
如果前i种数相加得到j-a[i]时第i种数还剩下k(k>0)个,用i种数相加得到j时,第i种数还剩余k-1个
b[i](dp[i][j]>=0)
dp[i+1][j]= -1(j<a[i]||dp[i+1][j-a[i]]<=0)
dp[i+1][j-a[i]]-1
#include<cstdio> #include<cstring> #include<iostream> using namespace std; int n,m; int a[100],b[100]; int dp[100]; void solve() { memset(dp,-1,sizeof(dp)); dp[0]=0; for(int i=0;i<n;i++) { for(int j=0;j<=m;j++) { if(dp[j]>=0)//前i种数已经组成j dp[j]=b[i]; else if(j<a[i]||dp[j-a[i]]<=0)//加a[i]就越界,或者b[i]<0 dp[j]=-1; else dp[j]=dp[j-a[i]]-1;//前i个数组成j-a[i],用一个a[i]组成j } } int ans=0; for(int i=1;i<=m;i++) { if(dp[i]>=0) { ans++; cout<<i<<" ";//可以组成的数分别时什么 } } cout<<endl; cout<<ans<<endl;//可以组成多少个数 //判断是否可以组成m // if(dp[m]>=0) // cout<<"yes"<<endl; // else // cout<<"no"<<endl; } int main() { while(cin>>n>>m) { for(int i=0;i<n;i++) { cin>>a[i]; } for(int i=0;i<n;i++) { cin>>b[i]; } solve(); } return 0; }