动态规划用法归纳

    在实际应用中,展示动态规划的用法。

    01背包问题

#include<iostream>
#include<cstring>

using namespace std;

int val[5000];
int wei[5000];
int f[13000];
inline int max(int a,int b)
{
    return a>b?a:b;
}
int main()
{
    memset(f,0,sizeof(f));
    int n,m;
    cin>>n>>m;
    for(int i=0;i<n;++i)
    cin>>wei[i]>>val[i];
    for(int i=0;i<n;++i)
    for(int j=m;j>=wei[i];j--)
    {
        f[j]=max(f[j-wei[i]]+val[i],f[j] );         //逗号前方表示包中选中此物品,后方表示上次状态容积为 j 时,对背包的使用
    }
    cout<<f[m]<<endl;
}
之所以要使 j 从容量循环到第 i 个包的质量,是因为只有在这个范围内才可能装下第 i 个物品。


举例2:点击打开链接

大意:一共有n个管道,每个管道的价格和流量不同,一个设备由不同的管道构成,每种管道有多种选择,他们的价格或流量不同,结果应选出价格之和最小与最小管道流量最大的组合。

#include<iostream>
#include<cstring>
#include<stdio.h>
#include<iomanip>
using namespace std;

#define max(a,b) (a>b?a:b)
struct reco
{
    int b;
    int p;
}re[120][120];
int mip[120];
int dp[120][1200];//dp[i][j],,,i表示第i号线路,j表示流量

int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        memset(dp,9999999,sizeof(dp));
        memset(re,0,sizeof(re));
        memset(mip,0,sizeof(mip));
        int line;
        cin>>line;
        int b,p,maxb=-99;
        for(int i=1;i<=line;++i)
        {
            cin>>mip[i];
            for(int q=1;q<= mip[i];++q)
            {
                cin>>b>>p;
                if(b>maxb)
                  maxb=b;
                re[i][q].b=b;
                re[i][q].p=p;
            }
        }
        for(int i=0;i<=maxb;++i)   //后面会用到dp[0][],而其值应为0.
           dp[0][i]=0;
        float ans=0;
        for(int i=1;i<=line;++i)
        for(int j=1;j<=mip[i];++j)
        {
            for(int k=1;k<=re[i][j].b;++k)
            dp[i][k]=min(dp[i][k],dp[i-1][k]+re[i][j].p); //前面有提示 k<=re[i][j],说明上次流量小于当前流量,进行更新
        }
        for(int i=1;i<=maxb;++i)
             ans=max(ans,1.0*i/dp[line][i]);
        cout<<fixed<<setprecision(3)<<ans<<endl;
    }
}


完全背包问题:

每种物品都可以取任意次。

#include<iostream>
#include<cstring>

using namespace std;
int min(int a,int b)
{
    return a>b?b:a;
}
int dp[10010];
int weic;//重量
int valc;//面值

int weight;

void solve()
{
    int n;
    cin>>n;
    for(int i=0;i<n;++i)
    {
        cin>>valc>>weic;
        if(dp[weic]==-1)
            dp[weic]=valc;
        else
            dp[weic]=min(dp[weic],valc);
        for(int j=0;j+weic<=weight;++j)
        {
           if(dp[j]==-1)
                continue;
           else if(dp[j+weic]==-1)
                dp[j+weic]=dp[j]+valc;
           else
                {
                     dp[j+weic]=min(dp[j+weic],dp[j]+valc);
                }
        }
    }
    if(dp[weight]!=-1)
    cout<<"The minimum amount of money in the piggy-bank is "<<dp[weight]<<"."<<endl;
    else
        cout<<"This is impossible."<<endl;
}
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        int b,a;
        cin>>b>>a;
        weight=a-b;
        memset(dp,-1,sizeof(dp));
        solve();
    }
}



未完待续。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值