赞
踩
输入:
- 5
- 4 4
- 1 1
- 5 2
- 5 5
- 4 3
输出:
10
解题思路:这个题一看很容易就会想到01背包DP,dp[i][j]表示从前i个物品中选,总重量为j的最大价值是多少,具体转移方程如下:
首先对于所有的j初始化:dp[i][j]=dp[i-1][j]
当前物品的重量w,价值v满足,v>=j时,dp[i][j+w]=max(dp[i][j+w],dp[i-1][j]+v)
然后就是排序问题,这是本题最主要的难点了(个人认为)。如果有两个物品i和j,i能放在j的上面,j却不能放在i的上面,此时这样的排列顺序是最优的,其应该满足如下关系式:
wi+sum<=vj
wj+sum>vi(sum为除了物品i,j之外的所有物品的重量和)
可得:wi<=vj,vi<wj
于是可以得到排序条件是wi+vi<wj+vj
上代码:
- #include <bits/stdc++.h>
- using namespace std;
- const int N=1010;
- struct node{
- int v;
- int w;
- }p[N];
- int n,dp[N][N*20];
- bool cmp(node a,node b)
- {
- return a.w+a.v<b.w+b.v;
- }
- int main()
- {
- cin>>n;
- for(int i=1;i<=n;i++)
- scanf("%d%d",&p[i].w,&p[i].v);
- sort(p+1,p+1+n,cmp);
- for(int i=1;i<=n;i++)
- {
- for(int j=0;j<=n*20;j++)
- dp[i][j]=dp[i-1][j];
-
- for(int j=p[i].v;j>=0;j--)
- dp[i][j+p[i].w]=max(dp[i][j+p[i].w],dp[i-1][j]+p[i].v);
- }
- int ans=-1;
- for(int i=n*20;i>=0;i--)
- ans=max(ans,dp[n][i]);
- cout<<ans<<endl;
- return 0;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。