DP问题

多重部分和问题

模板题

DP问题_第1张图片

DP问题_第2张图片

代码

#include
using namespace std;
#define Max_K 100000
int dp[Max_N+1][Max_K+1];
int a[Max_N];
int m[Max_N];
int n,K;
 
void solve()
{
    dp[0][0]=0;
    for(int j=1;j<=K;j++)
      dp[0][j]=-1;          //用前0种数凑成和不为0的,肯定不行
  
  //dp[i][j] 用前i种数(下标0~i-1)在能凑成和为j时,第i个数(下标为i-1)
  //最多可以剩余多少个,-1表示前i种数凑不成和为j 
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<=K;j++)
        {
            if(dp[i-1][j]>=0)     
            //如果前i-1种数就能凑成和为j,那么第i个数a[i-1]可以一个都不用,全部剩下来
                dp[i][j]=m[i-1];
            else             //前i-1种数凑不成和为j,那么就用第i个数a[i-1]尝试凑
            {
    //如果要凑的和j小于a[i-1],那么肯定凑不成j   ------   j=0表明前n个数(a[0]~a[n-1])在凑成和为K时,数a[i-1]不剩余或者还有剩余,
    //但是不管剩余还是不剩余,都是能凑成和为j 
    if(dp[n][K]>=0) cout<<"Yes\n";
    else cout<<"No\n";

    return ;
}

int main()
{
    cin>>n>>K;
    for(int i=0;i>a[i];
    }

    for(int i=0;i>m[i];
    }
    solve();
}

Holding Bin-Laden Captive!

这道题的数组得开的很小心,太小了会wa 太大了会MLE
定义dp[i][j]为前i种组成j的时候第i中数剩余多少

#include
#include
#include
using namespace std;
int dp[5][15000];
int a[4]={0,1,2,5};
int m[5];
int n,K=15000;

int main()
{
    while(cin>>m[1]>>m[2]>>m[3]&&(m[1]!=0||m[2]!=0||m[3]!=0)){
        memset(dp,-1,sizeof(dp));
        dp[0][0]=0;
        for(int i=1;i<=3;i++)
            for(int j=0;j<=K;j++){
                if(dp[i-1][j]>=0)
                    dp[i][j]=m[i];
                else if(a[i]>j||dp[i][j-a[i]]<=0){
                    dp[i][j]=-1;
                }else{
                    dp[i][j]=dp[i][j-a[i]]-1;
                }
            }
        int res;
        for(int j=0;j<=K;j++){
            if(dp[3][j]==-1)
            {
                res=j;
                break;
            }
        }
        cout<

你可能感兴趣的:(DP问题)