【BZOJ1742】[Usaco2005 nov]Grazing on the Run 邊跑邊喫草【區間DP】

【題目鏈接】

算是比較經典的區間DP,比較重要的思路是,把未來的花費放到現在計算。

一開始寫了個空間O(n^2)的記憶化搜索,結果被卡內存了,最後換成循環了...

/* Forgive me Not */
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int maxn = 3001, inf = 0x3f3f3f3f;

int n, s, pos[maxn], dp[maxn][2][2];

inline int iread() {
	int f = 1, x = 0; char ch = getchar();
	for(; ch < '0' || ch > '9'; ch = getchar()) f = ch == '-' ? -1 : 1;
	for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
	return f * x;
}

int main() {
	n = iread(); s = iread();
	for(int i = 1; i <= n; i++) pos[i] = iread();
	pos[++n] = s;
	sort(pos + 1, pos + 1 + n);
	s = lower_bound(pos + 1, pos + 1 + n, s) - pos;

	for(int i = 1; i <= n; i++) dp[i][1][0] = dp[i][1][1] = inf;
	dp[s][1][0] = dp[s][1][1] = 0;
	for(int i = 2; i <= n; i++) for(int l = 1; l <= n - i + 1; l++) {
		int r = l + i - 1;
		dp[l][i & 1][1] = min(dp[l + 1][~i & 1][1] + (n - i + 1) * (pos[l + 1] - pos[l]), dp[l + 1][~i & 1][0] + (n - i + 1) * (pos[r] - pos[l]));
		dp[l][i & 1][0] = min(dp[l][~i & 1][0] + (n - i + 1) * (pos[r] - pos[r - 1]), dp[l][~i & 1][1] + (n - i + 1) * (pos[r] - pos[l]));
	}
	printf("%d\n", min(dp[1][n & 1][0], dp[1][n & 1][1]));
	return 0;
}

記憶化搜索:

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int maxn = 3001, inf = 0x3f3f3f3f;

int n, s, pos[maxn], dp[maxn][maxn][2];

inline int iread() {
	int f = 1, x = 0; char ch = getchar();
	for(; ch < '0' || ch > '9'; ch = getchar()) f = ch == '-' ? -1 : 1;
	for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
	return f * x;
}

inline int iabs(int x) {
	return x < 0 ? -x : x;
}

inline int dfs(int l, int r, bool left) {
	if(l == r) return l == s ? 0 : inf;
	if(~dp[l][r][left]) return dp[l][r][left];
	int res = 0;
	if(left) res = min(dfs(l + 1, r, 1) + (n - r + l) * iabs(pos[l + 1] - pos[l]), dfs(l + 1, r, 0) + (n - r + l) * iabs(pos[r] - pos[l]));
	else res = min(dfs(l, r - 1, 0) + (n - r + l) * iabs(pos[r] - pos[r - 1]), dfs(l, r - 1, 1) + (n - r + l) * iabs(pos[r] - pos[l]));
	return dp[l][r][left] = res;
}

int main() {
	n = iread(); s = iread();
	for(int i = 1; i <= n; i++) pos[i] = iread();
	pos[++n] = s;
	sort(pos + 1, pos + 1 + n);
	s = lower_bound(pos + 1, pos + 1 + n, s) - pos;
	memset(dp, -1, sizeof(dp));
	printf("%d\n", min(dfs(1, n, 0), dfs(1, n, 1)));
	return 0;
}


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