用动规法实现0-1背包

实验名称
用动规法实现0-1背包。

实验目的
用动规法实现0-1背包:给你n个物品,每个物品有其重量和价值,现在有一个能装一定重量物品的背包,物品不能分割,要求能装下的最大价值。并输出最大价值下装载了哪几个物品。

实验原理
动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题。
但是经分解得到的子问题往往不是互相独立的。不同子问题的数目常常只有多项式量级。在用分治法求解时,有些子问题被重复计算了许多次。
如果能够保存已解决的子问题的答案,而在需要时再找出已求得的答案,就可以避免大量重复计算,从而得到多项式时间算法。

实验步骤
①用v[i]表示物品价值,w[i]表示物品重量。定义状态dp[i][j]以j为容量为放入前i个物品(按i从小到大的顺序)的最大价值;
②初始化边界条件,dp(0,j)=dp(i,0)=0;
③对于每一个物品,有两种选择方法,能装下和不能装下
1、包的容量比该商品体积小时装不下,此时的价值与前i-1个的价值是一样的,即dp(i,j)=dp(i-1,j);
2、还有足够的容量可以装该商品,但装了也不一定达到当前最优价值,所以在装与不装之间选择最优的一个,即dp(i,j)=max{dp(i-1,j),dp(i-1,j-w(i))+v(i)};其中dp(i-1,j)表示不装,dp(i-1,j-w(i))+v(i) 表示装了第i个商品,背包容量减少w(i)但价值增加了v(i);
④得到转移方程:
dp(i,j)=dp (i-1,j) j<w(i)
dp(i,j)=max{dp(i-1,j),dp(i-1,j-w(i))+v(i) } j>=w(i)

时间复杂度分析
利用动态规划解决此问题的递归式可得到动态规划的时间复杂度为O(n*c)。
实验心得 通过这次实验,我回顾了0-1背包问题与动态规划算法,让我对动态规划算法更加熟悉。

#include<iostream>
#include<fstream>
#include <windows.h> 
#include <time.h>
#include <stdlib.h> 
using namespace std;
void creatrand(long  int m) 
{
	ofstream f_out;
	f_out.open("input.txt", ios::out);
	srand(time(NULL));
	 int r,s;
	for ( int i = 0; i < m; i++)
	 {
		r =rand()%(10-1)+1;
		s =rand()%(10-1)+1;
		f_out<<r<<" "<<s<<endl;
	}
f_out.close();
}
 int main()
{
    int C,n;//c是容量,n是规模 
    ofstream f_out;
    f_out.open("output.txt");
    ifstream f_in("input.txt"); 
    cin >> C >> n;
    creatrand(n);
     int w[n],val[n];
    for( int i=1; i<=n; i++)
    {
    	f_in >> w[i]>>val[i];
        cout<< w[i]<<" "<<val[i]<<endl;
        f_out<< w[i]<<" "<<val[i]<<endl;
    }
     int dp[n][C];
    //初始化dp
	for( int i = 0;i <= C;i++){//当没有物品时,任何容量价值均为0 
		dp[0][i] = 0;
	} 
	for( int i = 0;i <= n;i++){//当容量为0时,任何物品都装不进去,价值为0 
		dp[i][0] = 0; 
	} 
	LARGE_INTEGER time,time0,time1,time2;
	QueryPerformanceFrequency(&time);
	QueryPerformanceCounter(&time0);
    for( int i=1; i<=n; i++) //物品 
        for( int j=C; j>=0; j--) //容量 
        {
            if(j >= w[i])
                dp[i][j] = max(dp[i-1][j-w[i]]+val[i], dp[i-1][j]);
            else      //只是为了好理解
                dp[i][j] = dp[i-1][j];           
        }
   QueryPerformanceCounter(&time1);
    cout << dp[n][C] << endl;
    cout<<"时间为:"<<1000.0*(time1.QuadPart-time0.QuadPart)/time.QuadPart<<"ms"<<endl;
    f_out<<dp[n][C]<<endl;
    f_out<<"时间为:"<<1000.0*(time1.QuadPart-time0.QuadPart)/time.QuadPart<<"ms"<<endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值