洛谷-最佳旅遊線路(P2096)

問題鏈接:

最佳旅遊線路

問題分析:

題目要求很簡單,遊客只能自左向右行走,但是可以南北隨意移動。然後給每段街道劃分數值,要求找出在這樣的情況下的最大數值。
藉助下圖進一步分析題目意思:
在這裏插入圖片描述
如上圖所示:典型的貪心問題,題目要求最終解所得數值最大,故每次選擇時都要保證選擇的是當前可供選項裏的最大值。如上例所示最優解必定是17,-3,36,34,-8的子集,因此此題的解也就可以用求解最大子數組的方法完成了。

問題求解:

法一:

#include<iostream>
using namespace std;
#define INT -1e7;

int maxCrossingSubarray(int *A, int lo, int mi, int hi){
 	int leftSum, rightSum;
 	leftSum = INT;
 	rightSum = INT;
 	int sum = 0;
 	for(int i = mi; i >= lo; i--){
 		sum += A[i];
  		if(sum > leftSum){
   			leftSum = sum;
  		} 
 	}
 	sum = 0;
 	for(int i = mi+1; i <= hi; i++){
  		sum += A[i];
  		if(sum > rightSum){
   			rightSum = sum;
  		} 
 	}
 	return leftSum + rightSum;
}
int maxSubarray(int *A, int lo, int hi){
 	if(lo == hi) return A[lo];
 	int mi = (lo+hi) / 2;
 	int left = maxSubarray(A, lo, mi);
 	int right = maxSubarray(A, mi+1, hi);
 	int cros = maxCrossingSubarray(A, lo, mi, hi);
 	if(left >= right && left >= cros)
  		return left;
 	else if(right >= left && right >= cros)
  		return right;
 	else return cros;
}

int main(){
 	int n, m;
 	cin >> n >> m;
 	int ars[n][m];
 	int val[m];
 	for(int i = 0; i < n; i++)
  		for(int j = 0; j < m; j++)
   			cin >> ars[i][j];
 	for(int i = 0; i < m; i++){//找出每一列最大值 
  		int max = ars[0][i];
  		for(int j = 1; j < n; j++){
   			if(max < ars[j][i])
   	 			max = ars[j][i];
  		}
  		val[i] = max;
 	}
 	//轉變爲求最大子數組問題 
 	cout << maxSubarray(val, 0, m-1);
 	return 0;
}

法二:

#include<iostream>
using namespace std;

int maxSubarray(int *A, int len){
 	int max = 0, sum = 0;
 	for(int i = 0; i < len; i++){
  		sum += A[i];
  		if(sum > 0){
  	 		if(sum > max)
    				max = sum;
  		} else 
   			sum = 0;
 		}
 	return max;
} 
int main(){
 	int n, m;
 	cin >> n >> m;
 	int ars[n][m];
 	int val[m];
 	for(int i = 0; i < n; i++)
  		for(int j = 0; j < m; j++)
  	 		cin >> ars[i][j];
 	for(int i = 0; i < m; i++){//找出每一列最大值 
  		int max = ars[0][i];
  		for(int j = 1; j < n; j++){
   			if(max < ars[j][i])
    				max = ars[j][i];
  		}
  		val[i] = max;
 	}
 	//轉變爲求最大子數組問題 
 	cout << maxSubarray(val, m);
 	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章