1. 程式人生 > >6045_開餐館

6045_開餐館

/*
	Name: 6045_開餐館
	Copyright: 
	Author: 
	Date: 24-06-18 13:39
	Description:
描述
北大資訊學院的同學小明畢業之後打算創業開餐館.現在共有n 個地點可供選擇。小明打算從中選擇合適的位置開設一些餐館。這 n 個地點排列在同一條直線上。我們用一個整數序列m1, m2, ... mn 來表示他們的相對位置。由於地段關係,開餐館的利潤會有所不同。我們用pi 表示在mi 處開餐館的利潤。為了避免自己的餐館的內部競爭,餐館之間的距離必須大於k。請你幫助小明選擇一個總利潤最大的方案。

輸入
標準的輸入包含若干組測試資料。輸入第一行是整數T (1 <= T <= 1000) ,表明有T組測試資料。緊接著有T組連續的測試。每組測試資料有3行,
第1行:地點總數 n (n < 100), 距離限制 k (k > 0 && k < 1000).
第2行:n 個地點的位置m1 , m2, ... mn ( 1000000 > mi > 0 且為整數,升序排列)
第3行:n 個地點的餐館利潤p1 , p2, ... pn ( 1000 > pi > 0 且為整數)
輸出
對於每組測試資料可能的最大利潤
樣例輸入
2
3 11
1 2 15
10 2 30
3 16
1 2 15
10 2 30
樣例輸出
40
30
*/
#include<iostream>
#include<cstdio>
#include<cstring>

using namespace std;

const int MAX = 1000; 
long long A[MAX+1]; //各點位置座標 
long long P[MAX+1]; //各點餐館利潤 
long long B[MAX+1]; //給定n個點開餐館的最大利潤 

long long DP(int n, int d);
long long DP_2(int n, int d); //動態規劃:類似最長上升子序列演算法 

int main() 
{
	int d, n, t;
	cin >> t;
	for (int i=0; i<t; i++)
	{
		cin >> n >> d;
		for (int j=1; j<=n; j++)
		{
			cin >> A[j];
		}
		for (int j=1; j<=n; j++)
		{
			cin >> P[j];
		}
		memset(B, 0, sizeof(B));
		cout << DP(n, d) << endl;
	}
	
    return 0;
}

long long DP(int n, int d) //動態規劃:類似最長上升子序列演算法 
{
	B[1] = P[1]; //只在位置1開餐館 
	for (int i=2; i<=n; i++)
	{
		B[i] = max(B[i-1], P[i]); //比較不在位置i開餐館和只在位置i開餐館的大小  
		for (int j=i-1; j>0; j--)//尋求利潤最大的開餐館方法 
		{
			if (A[i] - A[j] > d && B[i] < B[j]+P[i])//找到第一個滿足條件的就可以跳出迴圈了 
			{
				B[i] = B[j]+P[i];
				break;
			}
		}
	}
	
	return B[n];
}

long long DP_2(int n, int d) //動態規劃:類似最長上升子序列演算法 
{
	for (int i=1; i<=n; i++)
	{ 
		int j = i - 1;
		while (j>0 && A[i]-A[j]<=d)//找到第一個滿足條件的就可以跳出迴圈了 
			j--;
		B[i] = max(B[i-1], B[j]+P[i]);
	}
	
	return B[n];
}