您的位置:首页 > 其它

ZOJ 3537 Cake(凸包+区间DP)

2015-01-20 22:41 316 查看
思路:先判断是不是凸包,如果是的话,进行区间DP,

dp[i][j] = min{dp[i][k] + dp[k][j] + cost[i][k] + cost[k[[j]}

代码:

#include<cstdio>
#include<cmath>
#include <cstring>
#include <cstdlib>
#include<algorithm>
using namespace std;

const int MAXN= 305;
const int N = 305;

struct Point {
int x, y;
void read() {
scanf("%d%d", &x, &y);
}
} list[MAXN];

int stack[MAXN], top;

int xmult(Point p0, Point p1, Point p2) {
return (p1.x - p0.x) * (p2.y - p0.y) - (p1.y - p0.y) * (p2.x - p0.x);
}

double dist(Point p1,Point p2) {
return sqrt((double)(p2.x-p1.x)*(p2.x-p1.x)+(p2.y-p1.y)*(p2.y-p1.y));
}

//极角排序函数 , 角度相同则距离小的在前面
bool cmp(Point p1,Point p2) {
int tmp= xmult(list[0], p1, p2);
if(tmp > 0) return true;
else if(tmp == 0 && dist(list[0], p1) < dist(list[0], p2)) return true;
else return false;
}

//输入并把最左下方的点放在list[0]并且进行极角排序
void init(int n) {
int i, k;
Point p0;
//scanf("%d%d", &list[0].x, &list[0].y);
p0.x = list[0].x;
p0.y = list[0].y;
k = 0;
for(i = 1; i < n; i++) {
//scanf("%d%d", &list[i].x, &list[i].y);
if((p0.y > list[i].y) || ((p0.y == list[i].y) && (p0.x > list[i].x))) {
p0.x = list[i].x;
p0.y = list[i].y;
k = i;
}
}
list[k] = list[0];
list[0] = p0;
sort(list + 1, list + n, cmp);
}

int graham(int n) {
int i;
if(n == 1) {top = 0; stack[0] = 0;}
if(n == 2) {
top = 1;
stack[0] = 0;
stack[1] = 1;
}
if(n > 2) {
for(i = 0; i <= 1; i++) stack[i] = i;
top = 1;
for(i = 2; i < n; i++) {
while(top > 0 && xmult(list[stack[top - 1]], list[stack[top]], list[i]) <= 0) top--;
top++;
stack[top]=i;
}
}
return top + 1;
}

const int INF = 0x3f3f3f3f;
int n, p, cost

, dp

;

int main() {
while (~scanf("%d%d", &n, &p)) {
for (int i = 0; i < n; i++) list[i].read();
init(n);
if (n != graham(n)) {
printf("I can't cut.\n");
continue;
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (i == j || (i + 1) % n == j || i == (j + 1) % n) continue;
cost[i][j] = abs(list[i].x + list[j].x) * abs(list[i].y + list[j].y) % p;
}
}
for (int len = 2; len < n; len++) {
for (int l = 0; l + len < n; l++) {
int r = l + len;
dp[l][r] = INF;
for (int k = l + 1; k <= r - 1; k++) {
dp[l][r] = min(dp[l][r], dp[l][k] + dp[k][r] + cost[l][k] + cost[k][r]);
}
}
}
printf("%d\n", dp[0][n - 1]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: