開餐館 OpenJ_Bailian - 4118 (動態規劃 + 滾動陣列)
阿新 • • 發佈:2018-11-19
這題還算是一道比較基礎的動態規劃問題啦, 和01揹包問題略有類似, 都需要考慮容量和複雜度優化, 之前定義狀態總想著能二維就二維, 現在看來很多時候其實可以直接用一維的思路去定義狀態, 反而會簡便很多
定義dp[i] : 前i個地點產生的最大利潤(題目給出已排序的座標, 省去了排序)
然後考慮到對於每個地點我們都有選與不選兩種操作, 考慮需要再新增一個迴圈j : 來考慮第j個地點是否會是最優解
切記dp[i]的初始化就是d[i], 也就是到第i個地點至少的利潤, 再注意判斷相距要大於d
可得狀態轉移方程: dp[i] = dp{dp[i], dp[j] + d[i] | dp[i] - dp[j] > k}
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #include <string> #include <vector> #include <queue> #include <cmath> using namespace std; #define ms(x, n) memset(x,n,sizeof(x)); typedef long long LL; const LL maxn = 110; int T, n, k; int p[maxn], m[maxn]; int dp[maxn]; //在前i個餐館裡取得的最大價值 int solve() { for(int i = 1; i <= n; i++) //i表示第i個餐館 for(int j = 1; j < i; j++){ //找到一個最大價值的位置 if(m[i] - m[j] > k) dp[i] = max(dp[i], dp[j]+p[i]); } int ans = 0; for(int i = 1; i <= n; i++) ans = max(dp[i], ans); return ans; } int main() { cin >> T; while(T--){ cin >> n >> k; for(int i = 1; i <= n; i++) cin >> m[i]; for(int i = 1; i <= n; i++){ cin >> p[i]; dp[i] = p[i]; } cout << solve() << endl; } return 0; }