背包dp

Cut Ribbon

#include<bits/stdc++.h>
using namespace std;
const int N=4e3+10;
int dp[N],v[4];            //dp[i]表示长度 为i最多能够分成几段
int main(){              
    int n;
    cin>>n>>v[0]>>v[1]>>v[2];
    for(int i=0;i<=n;i++){
        for(int j=0;j<3;j++){
            if(i==v[j]||(i>v[j]&&dp[i-v[j]])){
          //状态转移方程
                dp[i]=max(dp[i],dp[i-v[j]]+1);
            }
        }
    }
    cout<<dp[n]<<endl;
}

樱花(多重背包,二进制拆分)

经典多重背包

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10,M=2e4+10;
int v[N],w[N],s[N],ww[N],vv[N],cnt,n;
int dp[M];
void init(){
    for(int i=1;i<=n;i++){
        int k=1;
        while(s[i]){
            cnt++;
            vv[cnt]=k*v[i];
            ww[cnt]=k*w[i];
            s[i]-=k;
            k*=2;
            if(s[i]<k){
                cnt++;
                vv[cnt]=v[i]*s[i];
                ww[cnt]=s[i]*w[i];
                break;
            }
        }
    }
}
int main(){
    int h1,m1,h2,m2;
    scanf("%d:%d %d:%d",&h1,&m1,&h2,&m2);
    int t=(h2-h1)*60+m2-m1;
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>v[i]>>w[i]>>s[i];
        if(s[i]==0)s[i]=t/v[i];
    }

    init();

    for(int i=1;i<=cnt;i++){
        for(int j=t;j>=vv[i];j--){
            dp[j]=max(dp[j],dp[j-vv[i]]+ww[i]);
        }
    }
    cout<<dp[t]<<endl;
}

 

posted @ 2022-10-19 23:29  Dengpc  阅读(45)  评论(0)    收藏  举报