UVa OJ1331
如果理解了,最优矩阵链乘(uvaoj348) 这个题也就好写多了,都是区间上的规划,管理。这个题,是区间上划分成三个区,一个三角形 和 它的左右两个区间,组成了一个大区间。
通过对三角形 和两个区间(这两个对应的区间上存的是的该区间上划分出来的最大三角形的最小面积),比较出最大的那个三角形 ,不断地更新整个大区间取最大三角形的最小的面积,最终区间所存的值为 最大三角形的最小面积。
连续区间的规划!重要的事情说三遍。
其实,这个题多了一个特点是 要考虑,所枚举的三角形内是否有其他的点,有其他的点,说明一定有冲突,与其他的线相交了,我们所枚举的一定是不想交的三角形 与 之对应区间的比较。
注意点:
1. 运用向量的知识,轻松通过求解面积解决 点在三角形内的问题。
2. 注意区间上存的是什么。
对了在 debung 中,有没有,试过,
1
1
3 0 (随便一个点)只有一组数据的,答案是1061109567.0 (3F3F3F3F)这是系统定义INF的初值。
看 0<x ,y<10000 , n<50 ,比较大。 不过 INF 1 << 30 也可以通过呦!!
递推:
#include<stdio.h> #include<math.h> #include<string.h> #define max(a,b) a>b?a:b #define min(a,b) a<b?a:b #define INF 1<<30 #define esp 1e-6 double dp[55][55]; int x[55],y[55]; int n; double area(int a,int b,int c) { return fabs( (x[b] - x[a])*(y[c]-y[a]) - (x[c] - x[a])*(y[b] - y[a]))*0.5; } int check(int k,double sum,int i,int j) { int c; for(c = 0;c<n;c++ ) { if(c == i|| c == j|| c== k)continue; if(fabs(sum - (area(c,i,j)+area(c,i,k)+area(c,j,k)))<esp )break; } if(c == n)return 1; return 0; } int main() { int i,j,d,k,t; double sum,m; scanf("%d",&t); while(t--) { scanf("%d",&n); for( i = 0;i<n;i++) { for( j = 0;j<n;j++) dp[i][j] = INF; } for(i =0;i<n;i++) { scanf("%d %d",&x[i],&y[i]); } for(i = 0;i<n;i++) dp[i][i+1]= 0; for(d =2;d<n;d++) for( i = 0;i+d<n;i++) { j = i+d; for(k =i+1 ;k<j;k++) { sum = area(k,i,j); if(check(k,sum,i,j)) { m = max( dp[i][k] ,dp[k][j]); m = max(m,sum); dp[i][j] = min(dp[i][j] ,m);//不知道为啥,我要是写成一个整体,精度就丢失了,调了半天!!!!tell me why!于是就分开写了 } } } printf("%.1f\n",dp[0][n-1]); } return 0; }
记忆化搜索:
#include<stdio.h> #include<math.h> #include<string.h> #define max(a,b) a>b?a:b #define min(a,b) a<b?a:b #define INF 1<<30; #define esp 1e-6 double dp[55][55]; int x[55],y[55]; int n; double area(int a,int b,int c) { return fabs( (x[b] - x[a])*(y[c]-y[a]) - (x[c] - x[a])*(y[b] - y[a]))*0.5; } double dfs(int i,int j) { int k,c;double r,l,m; if(j - i == 1)return dp[i][j] = 0.0; if(dp[i][j] >esp ) { return dp[i][j]; } double sum; double ans = INF; for( k = i+1; k < j; k++) { sum = area(k,i,j); for(c = 0;c<n;c++) { if(c == i || c==j || c==k)continue; if( fabs(sum - (area(c,i,j)+area(c,i,k)+area(c,j,k)))<esp )break; } if(c == n) { l = dfs(i,k); r = dfs(k,j); m = max(l,r); m = max(m,sum); ans= min(m ,ans); } } return dp[i][j]= ans; } int main() { int i,j; int t; scanf("%d",&t); while(t--) { scanf("%d",&n); memset(dp,-1,sizeof(dp)); for(i =0;i<n;i++) { scanf("%d %d",&x[i],&y[i]); } printf("%.1f\n",dfs(0,n-1)); } return 0; }