题目大意:
按照顺时针或者逆时针的顺序给出多边的点,要将这个多边形分解成n-2个三角形,要求使得这些三角行中面积最大的三角形面积尽量小,求最小值。
/* dp[i][j]表示从第i个点到第j个点,划分成j-i-1个三角形的最优解,然后每次转移时,枚举长度和左边界始点,那么根据长度和左边界点就可以知道右边界点,然后枚举左边界和右边界中间的点k,dp[i][j] = min(dp[i][j], max(max(dp[i][k], dp[k][j]), Area(i, k, j)).但是有一个问题,即i,k,j三点围成的三角形是否符合要求,判断的条件即为是否存在除i,k,j三点外的一点位于三角形中,有面积法判断。 */ #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; const int N = 100; const double INF = 0x3f3f3f3f3f3f; const double eps = 1e-9; struct point { double x, y; void get() { scanf("%lf%lf", &x, &y); } }p[N]; int n; double dp[N][N]; double area (point a, point b, point c) { return fabs((b.x-a.x)*(c.y-a.y) - (c.x-a.x)*(b.y-a.y))/2; } bool judge(int a,int b,int c) {//是否存在除i,k,j三点外的一点位于三角形中 double cur=area(p[a],p[b],p[c]); for(int i=0;i<n;i++) { if(i==a||i==b||i==c) continue; double tmp=area(p[a],p[b],p[i])+area(p[b],p[c],p[i])+area(p[c],p[a],p[i]); if(fabs(tmp-cur)<eps) return false; } return true; } double solve () { for (int i = 0; i < 2; i++) { for (int j = 0; j < n; j++) dp[j][(j+i)%n] = 0; } for (int i = 0; i < n; i++) dp[i][(i+2)%n] = area(p[i], p[(i+1)%n], p[(i+2)%n]); for(int k=3;k<n;k++){ for(int i=0;i<n;i++){ int t=(i+k)%n; dp[i][t]=INF; for(int j=(i+1)%n;j!=t;j=(j+1)%n){ if(judge(i,t,j))dp[i][t]=min(dp[i][t],max(max(dp[i][j],dp[j][t]),area(p[i], p[j], p[t]))); } } } double ans = INF; for (int i = 0; i < n; i++) ans = min (ans, dp[i][(i+n-1)%n]); return ans; } int main () { freopen("Cola.in","r",stdin); int cas; scanf("%d", &cas); while (cas--) { scanf("%d", &n); for (int i = 0; i < n; i++) p[i].get(); printf("%.1lf ", solve()); } return 0; }
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> using namespace std; int t,n; const double INF = 0x3f3f3f3f3f3f; const double eps = 1e-9; double s[60][60][60],dp[60][60]; struct node{ double x,y; }pos[60]; double count(int i,int j,int k){//计算面积 double x1=pos[i].x,x2=pos[j].x,x3=pos[k].x; double y1=pos[i].y,y2=pos[j].y,y3=pos[k].y; double xx1=x1-x3,xx2=x2-x3; double yy1=y1-y3,yy2=y2-y3; double res=fabs((xx1*yy2-xx2*yy1)/2.0); return res; } bool judge(int a,int b,int c){ double cur=s[a][b][c]; for(int i=1;i<=n;i++){ if(i==a||i==b||i==c)continue; double tmp=s[a][b][i]+s[a][c][i]+s[b][c][i]; if(fabs(tmp-cur)<=eps)return 0; } return 1; } int main(){ freopen("Cola.in","r",stdin); scanf("%d",&t); while(t--){ scanf("%d",&n); memset(s,0,sizeof(s)); memset(dp,0,sizeof(dp)); for(int i=0;i<n;i++)scanf("%lf%lf",&pos[i].x,&pos[i].y); for(int i=0;i<n;i++) for(int j=0;j<n;j++) for(int k=0;k<n;k++){ //s[i][j][k]=INF; if(i!=j&&i!=k&&j!=k) s[i][j][k]=count(i,j,k); } for(int i=0;i<n;i++)dp[i][(i+2)%n]=s[i][(i+1)%n][(i+2)%n]; for(int k=3;k<n;k++){ for(int i=0;i<n;i++){ int t=(i+k)%n; dp[i][t]=INF; for(int j=(i+1)%n;j!=t;j=(j+1)%n){ if(judge(i,t,j))dp[i][t]=min(dp[i][t],max(max(dp[i][j],dp[j][t]),s[i][j][t])); } } } double ans=INF; for(int i=0;i<n;i++) ans=min(ans,dp[i][(i+n-1)%n]); printf("%.1lf ",ans); } }
#include<iostream> #include<cstdio> #include<cstdlib> #include<ctime> using namespace std; int t,n; int main(){ srand(time(0)); t=rand()%6+2; printf("%d ",t); while(t--){ n=rand()%3+3; printf("%d ",n); for(int i=1;i<=n;i++){ int x=rand()%20+1,y=rand()%20+1; printf("%d %d ",x,y); } } }
#include<iostream> #include<cstdio> #include<cstring> #include<windows.h> using namespace std; int main(){ int t=1000000; while(t--){ system("1331_data>Cola.in"); system("1331_thmyl<Cola.in>1.out"); system("1331_std<Cola.in>2.out"); if(system("fc 1.out 2.out"))break; } system("pause"); }