java算法提高求最大值_算法提高 求最大值

算法提高 求最大值

时间限制:1.0s   内存限制:256.0MB

问题描述

给n个有序整数对ai bi,你需要选择一些整数对 使得所有你选定的数的ai+bi的和最大。并且要求你选定的数对的ai之和非负,bi之和非负。

输入格式

输入的第一行为n,数对的个数

以下n行每行两个整数 ai bi

输出格式

输出你选定的数对的ai+bi之和

样例输入

5

-403 -625

-847 901

-624 -708

-293 413

886 709

样例输出

1715

数据规模和约定

1<=n<=100

-1000<=ai,bi<=1000

话不多说开始动规,dp[i][j],i表示前i个数对,j表示所采取的数对的ai之和,dp[i][j]表示对应的bi之和。

首先考虑一个问题,题目要求的是ai之和非负,bi之和非负,还有一个隐藏的条件是,如果一个数对都不挑选的话,那么对应的结果应该是0。

所以我们考虑在输入期间就把ai为负值,bi也为负值的数对全部去除,因为一旦用到他们肯定不会是最优解。

状态方程:dp[i][j]=max(dp[i-1][j-ai]+bi,dp[i][j]);  j-ai是为了得到当没有加入ai时对应的dp值,所以dp[i-1][j-ai]+bi就是加入ai得到的dp值。对某一个状态来说,dp[i][j]+j就是他们的ai与bi之和。

将ai值和bi值偏移为正值之后的确就是一个很显然的背包问题。

需要注意的事,这题的状态转移比普通的背包要严苛得多。

在背包问题中,我们说在第i次选择时,当前状态dp[i][j]可以由两个状态转移而来,一个是dp[i][v-1],一个是dp[i-1][v-v[i]],但是在此题中只能是dp[i-1][j]和dp[i-1][j-a[i]]转移而来,直接承接上一行的值是因为,j表示的是ai之和,是限定死的。

#include

#define min 0x8f000000

using namespace std;

int n,a[105],b[105],dp[105][200005],pe=100000;//pe为偏移量   题目要求上限100个数,数值上下限为+ -1000,所以总区间长度为200000

int main()

{

int p,q,min1=min;

cin>>n;

int ans=0;

for(int i=1;i<=n;i++)

{

cin>>p>>q;

if(p<0&&q<0)

{

continue;

}

a[++ans]=p;

b[ans]=q;

}

for(int j=1;j<=ans;j++)

{

for(int k=-pe;k<=pe;k++)

{

dp[j][k+pe]=min1;

}

}

for(int o=1;o<=ans;o++)

{

dp[o][a[o]+pe]=b[o];

}

for(int u=2;u<=ans;u++)

{

for(int z=-pe;z<=pe;z++)

{

dp[u][z+pe]=max(dp[u-1][z+pe],dp[u][z+pe]);

if(z+pe-a[u]<0||z+pe-a[u]>200000)//加上a[i]是否越界  下一步状态转移中要求有dp[u-1][z+pe-a[i]],故需要越界判断   实际上要求ai之和非负,bi之和非负在这个判断中得以体现,并且最后的取最优是从pe开始的,z-a[u]这一步是为了得到之前的状态,若产生越界错误,即从如果当前的状态是a[u]放入后得到的,那么他的前一个状态并不能存在,那么状态转移有问题。

continue;

dp[u][z+pe]=max(dp[u][z+pe],dp[u-1][z+pe-a[u]]+b[u]);

}

}

int temp=min;

for(int y=0;y<=pe;y++)//也就是说在左端的值并没有进行考虑,在左端的值,就是ai之和为负值的情况

{

temp=max(temp,(dp[ans][y+pe]>=0?dp[ans][y+pe]+y:min1));

}

if(temp==min1)

{

cout<

}

else cout<

return 0;

}

唯一可能的问题是,为什么明明有偏移量,最后只需要一个dp[ans][y+pe]+y即可得到答案。

理由如下:实际上我们仅仅在

for(int o=1;o<=ans;o++){dp[o][a[o]+pe]=b[o];}

这里初始化的时候加了偏移量,在此之后的状态转移过程中,并没有再加偏移量,回到状态dp的定义,dp[i][j]表示的是在前i个数对中选择,选择得到的数对的ai之和为j,状态中存入的量为对应的bi之和。

dp[i][j+pe],j+pe仅仅是为了避免加上负值的ai导致越界而制造的偏移罢了,所以j+dp[i][j+pe]就是最终解。

至于为什么最后的解落在dp[n][0+pe]~dp[n][pe+pe],想必已经很明显了吧,题目要求ai之和非负,若是在dp[n][0]~dp[n][pe],减去偏移量后,对应的ai之和是负值,因此无须考虑。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值