01背包

来源:互联网 发布:如何用信用卡支付淘宝 编辑:程序博客网 时间:2024/06/06 06:28

滚动数组:

dp[j]=max(dp[j],dp[j-w]+v);

POJ 2184

将数组扩大100000,负数变为正数来处理

#include <iostream>#include <cstring>#include <string>#include <cstdio>using namespace std;#define inf 0x3f3f3f3ftypedef long long ll;const int maxn=2e5+10;int n,dp[maxn],s[1000],f[1000];int main(){    while(scanf("%d",&n)!=EOF)    {        for(int i=0;i<n;i++)            cin >> s[i] >> f[i];        for(int i=0;i<maxn;i++)            dp[i]=-inf;        dp[100000]=0;        for(int i=0;i<n;i++)        {            if(s[i]<0&&f[i]<0)                continue;            if(s[i]>0)            {                for(int j=200000;j>=s[i];j--)                    dp[j]=max(dp[j-s[i]]+f[i],dp[j]);            }            else            {                for(int j=s[i];j<=200000+s[i];j++)                    dp[j]=max(dp[j-s[i]]+f[i],dp[j]);            }        }        int ans=0;        for(int i=100000;i<=200000;i++)            if(dp[i]>=0)                ans=max(ans,dp[i]+i-100000);        cout << ans << endl;    }    return 0;}

POJ 2923

题意:有n种货物,有两辆车分别可以装C1,C2重量的货物,每次都必须两辆一起运送,问最少运送次数。

状压枚举出可以两辆车一次运完的状态,状压01.

#include <iostream>#include <string>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;#define inf 0x3f3f3f3ftypedef long long ll;const int maxn=1<<11;int dp[maxn],state[maxn],c[15],n,c1,c2,vis[maxn];bool check(int x){    memset(vis,0,sizeof(vis));    vis[0]=1;    int sum=0;    for(int i=0;i<n;i++)    {        if((x>>i)&1)        {            sum+=c[i];            for(int j=c1;j>=c[i];j--)                if(vis[j-c[i]])                    vis[j]=1;        }    }    for(int i=0;i<=c1;i++)        if(vis[i]&&sum-i<=c2)            return true;    return false;}int main(){    int t,num=1;    cin >> t;    while(t--)    {        cin >> n >> c1 >> c2;        for(int i=0;i<n;i++)            cin >> c[i];        int cnt=0,maxm=(1<<n)-1;        for(int i=1;i<=maxm;i++)            if(check(i))                state[cnt++]=i;        for(int i=0;i<maxn;i++)            dp[i]=inf;        dp[0]=0;        for(int i=0;i<cnt;i++)        {            for(int j=maxm-state[i];j>=0;j--)                if(!(state[i]&j))                    dp[state[i]|j]=min(dp[state[i]|j],dp[j]+1);        }        printf("Scenario #%d:\n%d\n\n",num++,dp[maxm]);    }    return 0;}

HDU 2546

先将钱数-5,再将最贵的拿出来被5减掉,然后对剩余的进行01

#include <iostream>#include <algorithm>#include <cstdio>#include <cstring>#include <string>using namespace std;typedef long long ll;const int maxn=1e3+10;int dp[maxn],d[maxn],n,m;int main(){    while(scanf("%d",&n)!=EOF)    {        if(n==0)            break;        int sum=0;        for(int i=0;i<n;i++)            cin >> d[i],sum+=d[i];        cin >> m;        sort(d,d+n);        if(m<5)        {            cout << m << endl;            continue;        }        if(sum<=m-5)        {            cout << m-sum << endl;            continue;        }        int res=m-5,x=5-d[n-1];        memset(dp,0,sizeof(dp));        for(int i=0;i<n-1;i++)        {            for(int j=res;j>=d[i];j--)            {                if(dp[j-d[i]]+d[i]>res)                    continue;                dp[j]=max(dp[j],dp[j-d[i]]+d[i]);            }        }        cout << res-dp[res]+x << endl;    }}

HDU 2639

求第K优解的01

#include <iostream>#include <algorithm>#include <cstring>#include <string>#include <cstdio>using namespace std;#define inf 0x3f3f3f3f#define PI acos(-1.0)typedef long long ll;const int maxn=1e3+10;int dp[maxn][35],v[maxn],d[maxn],V,K,a[maxn],b[maxn],n;int main(){    int t;    cin >> t;    while(t--)    {        cin >> n >> V >> K;        for(int i=1;i<=n;i++)            cin >> d[i];        for(int i=1;i<=n;i++)            cin >> v[i];        memset(dp,0,sizeof(dp));        int k;        for(int i=1;i<=n;i++)        {            for(int j=V;j>=v[i];j--)            {                for(k=1;k<=K;k++)                {                    a[k]=dp[j][k];                    b[k]=dp[j-v[i]][k]+d[i];                }                a[k]=-1,b[k]=-1;                int x=1,y=1,z=1;                while(z<=k&&(a[x]!=-1||b[y]!=-1))                {                    if(a[x]>b[y])                        dp[j][z]=a[x++];                    else                        dp[j][z]=b[y++];                    if(dp[j][z]!=dp[j][z-1])                        z++;                }            }        }        cout << dp[V][K] << endl;    }    return 0;}

HDU 2126

求最优方案总数

#include <iostream>#include <algorithm>#include <cstdio>#include <cstring>#include <string>using namespace std;typedef long long ll;const int maxn=510;int dp[maxn],g[maxn],n,m,v[maxn];int main(){    int t;    cin >> t;    while(t--)    {        cin >> n >> m;        for(int i=0;i<n;i++)            cin >> v[i];        for(int i=0;i<=m;i++)            g[i]=1;        memset(dp,0,sizeof(dp));        for(int i=0;i<n;i++)        {            for(int j=m;j>=v[i];j--)            {                if(dp[j]<dp[j-v[i]]+1)                    dp[j]=dp[j-v[i]]+1,g[j]=g[j-v[i]];                else if(dp[j]==dp[j-v[i]]+1)                    g[j]=g[j-v[i]]+g[j];            }        }        if(dp[m])        {            printf("You have %d selection(s) to buy with %d kind(s) of souvenirs.\n",g[m],dp[m]);        }        else            printf("Sorry, you can't buy anything.\n");    }    return 0;}

UVA 624

记录01背包的路径

#include <bits/stdc++.h>using namespace std;typedef long long ll;const int maxn=1e4+10;int dp[maxn],v[30],vis[30][maxn],n,m;int main(){    while(scanf("%d",&m)!=EOF)    {        cin >> n;        for(int i=0;i<n;i++)            cin >> v[i];        memset(dp,0,sizeof(dp));        memset(vis,0,sizeof(vis));        for(int i=0;i<n;i++)        {            for(int j=m;j>=v[i];j--)            {                if(dp[j]<=dp[j-v[i]]+v[i])                    dp[j]=dp[j-v[i]]+v[i],vis[i][j]=1;            }        }        int k=m;        for(int i=n;i>=0;i--)        {            if(vis[i][k])            {                cout << v[i] << " ";                k-=v[i];            }        }        cout << "sum:" << dp[m] << endl;    }    return 0;}


原创粉丝点击