1. 程式人生 > >算法提高 求最大值

算法提高 求最大值

one default range 偏移量 small table bsp 最大 wrap

問題描述   給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 01背包變種,復制一下別人的思路: 不直接計算選定的數的ai+bi的和,而是轉化為計算在ai的和一定的情況下盡量使選定的bi的和最大。於是變成為一個和01背包差不多的問題。首先過濾掉所有ai和bi均小於0的數對,令dp[i][j]表示前i個數對,選定的ai的和為j的情況下bi的和的最大值,將dp[i][j]初始化為-INF,再將所有已知合法情況初始化:dp[i][a[i]] = b[i],之後dp[i][j] = max(dp[i - 1][j], dp[i][j]),若j - a[i]存在,dp[i][j] = max(dp[i][j], dp[i - 1][j - a[i]] + b[i])。為避免負數作為數組下標,要加一個偏移量。
來源: http://www.cnblogs.com/wangyiming/p/6476019.html
 1 #include<stdio.h>
 2 
 3 #define Max(a,b)  ((a>b)?(a):(b))
 4 #define N  100000
 5 
 6 void input( int [] , int [] , int );
 7 int maxNum( int [] , int [] , int );
 8 
 9 int main(void)
10 {
11     int n ;
12     scanf("%d" , &n );
13     
14     int Na[n] , Nb[n] ;
15     input( Na , Nb , n );
16 17 int ans = maxNum( Na , Nb , n ); 18 printf("%d\n", ans >= 0 ? ans : 0 ); 19 return 0; 20 } 21 22 void input( int Na[] , int Nb[] , int n ){ 23 while( n -- ){ 24 scanf("%d%d", Na ++ , Nb ++ ); 25 } 26 } 27 28 int maxNum( int Na[] , int Nb[] , int n ){ 29 static
int dp[100][N*2+1] = {0} ; 30 int res = -N ; 31 int i , j ; 32 for( i = 0 ; i < n ; i ++ ){ 33 for( j = -N ; j <= N ; j ++ ){ 34 dp[i][j + N] = -N ; 35 } 36 } 37 38 for( i = 0 ; i < n ; i ++ ){ 39 dp[i][N + Na[i]] = Nb[i] ; 40 } 41 42 for( i = 1 ; i < n ; i ++ ){ 43 for( j = -N ; j <= N ; j ++ ){ 44 dp[i][j + N] = Max(dp[i][j + N] , dp[i-1][j + N]); 45 46 if( j + N - Na[i] >= 0 && j + N - Na[i] < N*2 ){ 47 dp[i][j + N] = Max( dp[i][j + N] , dp[i-1][j + N - Na[i]] + Nb[i] ); 48 } 49 } 50 } 51 52 for( j = 0 ; j <= N ; j ++ ){ 53 if( dp[n-1][j + N] >= 0 ){ 54 res = Max( res , j + dp[n-1][j + N] ); 55 } 56 } 57 58 return res; 59 }

算法提高 求最大值