动态规划:01背包问题、多段图问题

本文介绍两种经典的动态规划问题实现:01背包问题和多段图问题。01背包问题通过二维数组记录每种物品组合的最大价值,最终求得最优解;多段图问题则采用动态规划寻找从起点到终点的最短路径。

1,01背包问题

#include<iostream>
#include<cstring>
using namespace std;

int n;      //物品个数
int c;      //背包容量
int w[20];    //n个物品的重量
int v[20];    //n个物品的价值

int summax[20][20]; //最大价值数组
int x[20];    //存储装入背包的物品

int f(int n,int w[],int v[])
{
    for(int i=0;i<=n;i++) //初始化第0列
    {
        summax[i][0]=0;
    }
    for(int j=0;j<=c;j++) //初始化第0行
    {
        summax[0][j]=0;
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=c;j++)
        {
            if(j<w[i])
            {
                summax[i][j]=summax[i-1][j];
            }
            else{
                summax[i][j]=max(summax[i-1][j],summax[i-1][j-w[i]] + v[i]);
            }
        }
    }
    int j=c;    //求装入背包的物品
    for(int i=n;i>0;i--)
    {
        if(summax[i][j]>summax[i-1][j])
        {
            x[i]=1;
            j=j-w[i];
        }else{
            x[i]=0;
        }
    }
    return summax[n][c];  //返回背包取得的最大价值
}

int main()
{
    memset(w,0,sizeof(w));
    memset(v,0,sizeof(v));
    memset(summax,0,sizeof(summax));
    memset(x,0,sizeof(x));

    cout<<"请输入物品个数:";
    cin>>n;
    cout<<"请依次输入物品重量:";
    for(int i=1;i<=n;i++)
    {
        cin>>w[i];
    }
    cout<<"请依次输入物品价值:";
    for(int i=1;i<=n;i++)
    {
        cin>>v[i];
    }
    cout<<"请输入背包总容量:";
    cin>>c;

    cout<<"可获得的最大价值为:"<<f(n,w,v)<<endl;
    cout<<"装入背包的物品为:";
    for(int i=1;i<=n;i++)
    {
        if(x[i]==1)
        {
            cout<<"物品"<<i<<" ";
        }
    }
    return 0;
}

2,多段图问题

//ppt p9页 动态规划例题 多段图问题

#include<iostream>
#include<cstring>
using namespace std;
int cost[10];
int path[10];
int array1[10][10];

int main()
{
    memset(cost,0,sizeof(cost));
    memset(path,0,sizeof(path));
    memset(array1,0,sizeof(array1));
    cout<<"请输入多变图的段数:"<<endl;
    int m; //18
    cin>>m;
    cout<<"请依次输入多段图的起点终点和路径长度"<<endl;
    int start;
    int stop;
    int length;
    for(int i=0;i<18;i++)
    {
        cin>>start>>stop>>length;
        array1[start][stop]=length;
    }
    for(int i=8;i>=0;i--)
    {
        cost[i]=9999;
        for(int j=i;j<10;j++)
        {
            if(array1[i][j]!=0)//等于0表示之间没有路
            {
                if(array1[i][j]+cost[j]<cost[i])//此时找到一条更短的路
                {
                    path[i]=j;  //更新path[i]
                    cost[i]=array1[i][j]+cost[j]; //更新从该节点出发的最短路径
                }
            }
        }

    }
    cout<<"最短路径长度是:"<<cost[0]<<endl;
    cout<<"最短路径为:"<<endl;
    int i=0;
    cout<<"0--->";
    while(true)
    {
        cout<<path[i];
        i=path[i];
        if(i==9)
        {
            break;
        }
        cout<<"--->";
    }
    return 0;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

weixin_39450145

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值