【DP】HDOJ 3480 Division
2236 ワード
傾きDP。参照http://www.cnblogs.com/ka200812/archive/2012/08/03/2621345.html
#include <iostream>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <climits>
#include <cstdlib>
#include <cmath>
#include <time.h>
#define maxn 1005
#define maxm 300006
#define eps 1e-10
#define mod 1315423911
#define INF 1e9
#define lowbit(x) (x&(-x))
#define mp make_pair
#define ls o<<1
#define rs o<<1 | 1
#define lson o<<1, L, mid
#define rson o<<1 | 1, mid+1, R
typedef long long LL;
typedef unsigned long long ULL;
//typedef int LL;
using namespace std;
int n, m;
int a[10005];
void read(void)
{
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
}
int cmp(int a, int b)
{
return a < b;
}
int dp[5005][10005];
int q[10005];
bool check1(int aa, int bb, int cc, int now)
{
int y1 = dp[now][aa] + a[aa+1] * a[aa+1];
int y2 = dp[now][bb] + a[bb+1] * a[bb+1];
int y3 = dp[now][cc] + a[cc+1] * a[cc+1];
int x1 = 2 * a[aa+1];
int x2 = 2 * a[bb+1];
int x3 = 2 * a[cc+1];
return (y3 - y2) * (x2 - x1) <= (y2 - y1) * (x3 - x2);
}
bool check2(int aa, int bb, int now, int res)
{
int y1 = dp[now][aa] + a[aa+1] * a[aa+1];
int y2 = dp[now][bb] + a[bb+1] * a[bb+1];
int x1 = 2 * a[aa+1];
int x2 = 2 * a[bb+1];
return (y2 - y1) <= (x2 - x1) * res;
}
void work(void)
{
sort(a+1, a+n+1, cmp);
for(int i = 1; i <= n; i++) dp[1][i] = (a[i] - a[1]) * (a[i] - a[1]);
for(int i = 2; i <= m; i++) {
int f = 0, t = 0;
dp[i][1] = 0;
for(int j = 1; j < n; j++) {
while(t - f > 1 && check1(q[t-2], q[t-1], j, i-1)) t--;
q[t++] = j;
while(t - f > 1 && check2(q[f], q[f+1], i-1, a[j + 1])) f++;
dp[i][j+1] = dp[i-1][q[f]] + (a[j+1] - a[q[f] + 1]) * (a[j+1] - a[q[f] + 1]);
}
}
printf("%d
", dp[m][n]);
}
int main(void)
{
int _, __;
while(scanf("%d", &_)!=EOF) {
__ = 0;
while(_--) {
read();
printf("Case %d: ", ++__);
work();
}
}
return 0;
}