算法提高 求最大值


  算法提高 求最大值  
時間限制: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<iostream>
#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<<"0";
}
else cout<<temp;
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之和是負值,因此無須考慮。


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com