[BZOJ1575] [Usaco2009 Jan]气象牛Baric(DP)

传送门

 

DP

f[i][j]表示前i个中选j个的最优解

预处理g[i][j]表示选i~j对答案的贡献

那么就可以n^3乱搞了!

注意边界

 

#include <cstdio>
#include <cstring>
#include <iostream>
#define N 110
#define abs(x) ((x) < 0 ? -(x) : (x))
#define min(x, y) ((x) < (y) ? (x) : (y))

int n, e, ans;
int a[N], f[N][N], g[N][N];

inline int read()
{
	int x = 0, f = 1;
	char ch = getchar();
	for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
	for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0';
	return x * f;
}

int main()
{
	int i, j, k;
	n = read();
	e = read();
	for(i = 1; i <= n; i++) a[i] = read();
	for(i = 1; i < n; i++)
		for(j = 1; j <= i; j++)
			g[1][i] += 2 * abs(a[j] - a[i + 1]);
	for(i = 2; i <= n; i++)
		for(j = i; j <= n; j++)
			g[i][n] += 2 * abs(a[j] - a[i - 1]);
	for(i = 2; i < n; i++)
		for(j = i; j < n; j++)
			for(k = i; k <= j; k++)
				g[i][j] += abs(2 * a[k] - (a[i - 1] + a[j + 1]));
	memset(f, 127, sizeof(f));
	for(i = 1; i <= n; i++)
	{
		f[i][1] = g[1][i - 1] + g[i + 1][n];
		for(j = 2; j <= i; j++)
			for(k = 1; k < i; k++)
				if(f[k][j - 1] ^ f[0][0])
					f[i][j] = min(f[i][j], f[k][j - 1] - g[k + 1][n] + g[k + 1][i - 1] + g[i + 1][n]);
	}
	for(i = 1; i <= n; i++)
	{
		ans = ~(1 << 31);
		for(j = i; j <= n; j++)
			ans = min(ans, f[j][i]);
		if(ans <= e)
		{
			printf("%d %d\n", i, ans);
			break;
		}
	}
	return 0;	
}

  

posted @ 2017-09-12 09:03  zht467  阅读(175)  评论(0编辑  收藏  举报