papamelon 344. 奶牛展覽 Cow Exhibition(挑戰程序設計競賽) dp

地址 https://www.papamelon.com/problem/344

貝西有權選擇讓哪些奶牛參加展覽。
由於負的智商或情商會造成負面效果,所以貝西不希望出展奶牛的智商之和小於零,或情商之和小於零。
滿足這兩個條件下,她希望出展奶牛的智商與情商之和越大越好,請幫助貝西求出這個最大值。

輸入
第一行:單個整數 
1≤N≤100
第二行到第 N+1 行:第 
i+1 行有兩個整數:
Si 和 Fi,表示第 i 奶牛的智商和情商,
−1000≤Si,Fi≤1000
輸出
一個整數:表示情商與智商和的最大值
貝西可以不讓任何奶牛參加展覽,如果這樣做是最好的,輸出 
0
樣例 1
輸入
5
-5 7
8 -6
6 -3
2 1
-8 -5
輸出
8

解答
很明顯的揹包問題
但是在數據範圍上好多細節
一個是揹包的空間太大,需要做空間優化
一個是揹包的索引有的是負值。
我們定義dp[i][j] 表示前i個牛的情商爲j的情況下最大的智商爲多少
然後偏移j的索引爲 最大可能負值的一半,也就是100個牛情商全爲負數的情況下, maxIdx = 100*-1000/2

#include <iostream>
#include <algorithm>
#include <memory.h>
using namespace std;

const int N = 20010;
const int M = 110;
const int newZero = 10000;

int dp[M][N];
int n;
int arr[M][2];

int main()
{
	cin >> n;
	for (int i = 1; i <= n; i++) {
		cin >> arr[i][0] >> arr[i][1]; 
	}

	memset(dp, -0x3f, sizeof dp);
	dp[0][newZero] = 0;
	int ans = 0;
	for (int i = 1; i <= n; i++) {
		for (int j = 0; j < N; j++) {
			dp[i][j] = dp[i - 1][j];
			int eq = arr[i][0]; int iq = arr[i][1];

			if(j-eq <N)
				dp[i][j] = max(dp[i][j], dp[i - 1][j - eq] + iq);


			if (i == n && j >= newZero && dp[n][j] >= 0) {

				if (ans < j + dp[i][j] - newZero) {
					//printf("dp[%d][%d]=%d\n",i,j,dp[i][j]);
				}
				ans = max(ans, j + dp[i][j] - newZero);
				
			}
		}
	}

	cout << ans << endl;

	return 0;
}
能過部分數據,但是要過大數據,需要分配[100][2*2000*100]  會報空間過大,這時候我們需要做空間優化
使用滾動數組解決空間問題
#include <iostream>
#include <algorithm>
#include <memory.h>
using namespace std;


const int N = 200010;
const int M = 110;
const int newZero = 100000;

int dp[2][N];
int n;
int arr[M][2];

int main()
{
	cin >> n;
	for (int i = 1; i <= n; i++) {
		cin >> arr[i][0] >> arr[i][1]; 
	}

	memset(dp, -0x3f, sizeof dp);

	for (int i = 0; i < N; i++) {
		dp[0][i] = -999999999;
		dp[1][i] = -999999999;
	}

	dp[0][newZero] = 0;
	int ans = 0;
	int curr = 1; int prev = 0;
	for (int i = 1; i <= n; i++) {
		for (int j = 0; j < N; j++) {
			dp[curr][j] = dp[prev][j];
			int eq = arr[i][0]; int iq = arr[i][1];

			if(j-eq <N)
				dp[curr][j] = max(dp[curr][j], dp[prev][j - eq] + iq);


			if (i == n && j >= newZero && dp[curr][j] >= 0) {
				ans = max(ans, j + dp[curr][j] - newZero);
			}
		}
		swap(curr, prev);
	}

	cout << ans << endl;

	return 0;
}

視頻題解空間

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章