题意:给出一些点表示多边形顶点的位置(如果多边形是凹多边形就不能切),切多边形时每次只能在顶点和顶点间切,每切一次都有相应的代价。现在已经给出计算代价的公式,问把多边形切成最多个不相交三角形的最小代价是多少。
题目链接:https://vjudge.net/problem/23543/origin
#include<bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
const double eps = 1e-10;
double dcmp(double x) {
if(fabs(x) < eps) return 0;
else return x < 0 ? -1 : 1;
}
struct Point {
double x, y;
Point(double x=0, double y=0):x(x),y(y) {}
};
vector<Point> v;
Point operator - ( const Point &A ,const Point &B) {
return Point(A.x-B.x, A.y-B.y);
}
bool operator == (const Point& p1, const Point& p2) {
return p1.x == p2.x && p1.y == p2.y;
}
bool operator < (const Point& p1, const Point& p2) {
return p1.x < p2.x || (p1.x == p2.x && p1.y < p2.y);
}
double Cross(const Point& A, const Point& B) {
return A.x*B.y - A.y*B.x;
}
double Dot(const Point& A, const Point& B) {
return A.x*B.x + A.y*B.y;
}
int cross(Point p0,Point p1,Point p2) //计算叉积 p0p1 X p0p2
{
return (p1.x-p0.x)*(p2.y-p0.y)-(p1.y-p0.y)*(p2.x-p0.x);
}
double dis(Point p1,Point p2) //计算 p1p2的 距离
{
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=cross(v[0],p1,p2);
if(tmp>0) return true;
else if(tmp==0&&dis(v[0],p1)<dis(v[0],p2)) return true;
else return false;
}
vector<Point> ConvexHull(vector<Point> p) {
// 预处理,删除重复点
sort(p.begin(), p.end());
p.erase(unique(p.begin(), p.end()), p.end());
int n = p.size();
int m = 0;
vector<Point> ch(n+1);
for(int i = 0; i < n; i++) {
while(m > 1 && Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2]) <= 0) m--;
ch[m++] = p[i];
}
int k = m;
for(int i = n-2; i >= 0; i--) {
while(m > k && Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2]) <= 0) m--;
ch[m++] = p[i];
}
if(n > 1) m--;
ch.resize(m);
return ch;
}
int f[305][305];
int dp[305][305];
vector<Point> s;
int main(){
int n,m;
int xx,yy;
while(scanf("%d%d",&n,&m)>0){
for(int i=0;i<n;i++){
scanf("%d%d",&xx,&yy);
v.push_back({xx,yy});
}
s = ConvexHull(v);
if(s.size()!=n ){
cout << "I can't cut.\n";
v.clear();
continue;
}
else{
sizeof(f,0,sizeof(f));
for (int i=0; i<n; i++)
{
for (int j=i+2; j<n; j++)
f[i][j] = f[j][i] = ( ((ll)fabs(s[i].x + s[j].x) ) * ((ll)fabs(s[i].y + s[j].y) ))%m;
}
for (int i=0; i<n; i++)
{
for (int j=0; j<n; j++)
dp[i][j] = INF;
dp[i][(i+1)%n]=0;
}
for (int i=n-3; i>=0; i--)//区间dp求解
{
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]+f[i][k]+f[k][j]);
}
}
}
cout<<dp[0][n-1]<<endl;
}
v.clear();
s.clear();
}
}
/*
4 100
1 1
2 1
1 2
2 2
*/