转自:http://blog.csdn.net/woshi250hua/article/details/7824433
状态转移方程弄懂了,但是因为没有做计算几何,所以凸包的求解看不懂。。。。以后看。。。。先刷DP
AC代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define MAX 0x3f3f3f3f
int N, P;
typedef struct{
int x, y;
}Node;
Node point[1000], newpoint[1000];
int cost[1000][1000];
int dp[1000][1000];
inline int abs( int x ){
return x < 0 ? -x : x;
}
int xmult( Node p1, Node p2, Node p0 ){
return ( p1.x - p0.x ) * ( p2.y - p0.y ) - ( p2.x - p0.x ) * ( p1.y - p0.y );
}
bool cmp( const Node &a, const Node &b ){
if( a.y == b.y ){
return a.x < b.x;
}
return a.y < b.y;
}
int graham( Node *p, int n ){
int i;
sort( p, p + n, cmp );
newpoint[0] = point[0];
newpoint[1] = point[1];
int top = 1;
for( i = 0; i < n; i++ ){
while( top && xmult( newpoint[top], p[i], newpoint[top-1] ) >= 0 ){
top--;
}
newpoint[++top] = p[i];
}
int mid = top;
for( i = n - 2; i >= 0; i-- ){
while( top > mid && xmult( newpoint[top], p[i], newpoint[top-1] ) >= 0 ){
top--;
}
newpoint[++top] = p[i];
}
return top;
}
int Count( Node a, Node b ){
return ( abs( a.x + b.x ) * abs( a.y + b.y ) ) % P;
}
int main(){
while( scanf( "%d%d", &N, &P ) != EOF ){
for( int i = 0; i < N; i++ ){
cin >> point[i].x >> point[i].y;
}
int tot = graham( point, N );
if( tot < N ){
cout << "I can't cut." << endl;
}else{
memset( cost, 0, sizeof( cost ) );
for( int i = 0; i < N; i++ ){
for( int j = i + 2; j < N; j++ ){
cost[i][j] = cost[j][i] = Count( newpoint[i], newpoint[j] );
}
}
for( int i = 0; i < N; i++ ){
for( int j = 0; j < N; j++ ){
dp[i][j] = MAX;
}
dp[i][(i+1)%N] = 0;
}
for( int i = N - 3; i >= 0; i-- ){
for( int j = i + 2; j < N; j++ ){
for( int k = i + 1; k < j; k++ ){
dp[i][j] = min( dp[i][j], dp[i][k] + dp[k][j] + cost[i][k] + cost[k][j] );
}
}
}
cout << dp[0][N-1] << endl;
}
}
return 0;
}