uva1299 Frontier(环形dp)
2015-06-03 00:19
441 查看
关键词:判断点和向量的关系,环形dp
题意:已知平面内n个点的坐标(顺时针给出),试选出若顶点围城周长最小的多边形能够使得另外k个点在该多边形内部
解法:
1.枚举所有起点st。题目转化为顺序dp
2.对于包含st的多边形。设dp[i]:顺时针从st到i,能够使得k个点在该曲线”内部”的最小周长。
dp[i]=min(dp[j]+dis[i][j],k个点全都在从i点指向j点的向量的右侧)
结论:由A3作为顶点的三角形A1A2A3有向面积(x1-x3)(y2-y3)-(y1-y3)(x2-x3)
等于0:A3在向量A1->A2上
大于0:A3在向量A1->A2左侧
小于0:A3在向量A1->A2右侧
3.特判:当m==0时,题目要求面积非0,因此要找出面积非零的最小周长三角形
题意:已知平面内n个点的坐标(顺时针给出),试选出若顶点围城周长最小的多边形能够使得另外k个点在该多边形内部
解法:
1.枚举所有起点st。题目转化为顺序dp
2.对于包含st的多边形。设dp[i]:顺时针从st到i,能够使得k个点在该曲线”内部”的最小周长。
dp[i]=min(dp[j]+dis[i][j],k个点全都在从i点指向j点的向量的右侧)
结论:由A3作为顶点的三角形A1A2A3有向面积(x1-x3)(y2-y3)-(y1-y3)(x2-x3)
等于0:A3在向量A1->A2上
大于0:A3在向量A1->A2左侧
小于0:A3在向量A1->A2右侧
3.特判:当m==0时,题目要求面积非0,因此要找出面积非零的最小周长三角形
#include<stdio.h> #include<string.h> #include<math.h> #include<algorithm> #include<iostream> #include<vector> #include<map> #include<set> #define ll long long #define INF 0x3f3f3f3f using namespace std; const int maxn = 1000+10; int n,m; struct Edge{ int x,y; }tower[maxn],his[maxn]; bool vis[maxn][maxn]; double dp[maxn]; double dis[maxn][maxn]; double ans; //判断所有点是否在向量AB(x2-x1,y2-y1)右侧 bool judge(int x1,int y1,int x2,int y2){ for(int k=0;k<m;k++){ int x3=his[k].x,y3=his[k].y; if((x1-x3)*(y2-y3)-(y1-y3)*(x2-x3)>=0) return false; } return true; } int main(){ //freopen("a.txt","r",stdin); while(scanf("%d%d",&n,&m)!=EOF){ for(int i=0;i<n;i++){ scanf("%d%d",&tower[i].x,&tower[i].y); } for(int i=0;i<m;i++){ scanf("%d%d",&his[i].x,&his[i].y); } ans=INF; memset(vis,0,sizeof(vis)); for(int i=0;i<n;i++){ for(int k=1;k<n;k++){ int j=(i+k)%n; if(judge(tower[i].x,tower[i].y,tower[j].x,tower[j].y)) vis[i][j]=1; dis[i][j]=(double)sqrt((double)(tower[i].x-tower[j].x)*(tower[i].x-tower[j].x)+(double)(tower[i].y-tower[j].y)*(tower[i].y-tower[j].y)); } } //m==0时需要特判 if(m==0){ for(int i=0;i<n;i++){ for(int j=i+1;j<n;j++){ for(int k=j+1;k<n;k++){ if((tower[j].x-tower[i].x)*(tower[k].y-tower[i].y)-(tower[j].y-tower[i].y)*(tower[k].x-tower[i].x)) ans=min(ans,dis[i][j]+dis[j][k]+dis[k][i]); } } } printf("%.2lf\n",ans); continue; } for(int st=0;st<n;st++){ for(int i=0;i<n;i++) dp[i]=INF; dp[st]=0.0; for(int i=st+1;;i++){ if(i>=n) i%=n; if(i==st) break; for(int j=i-1;;j--){ if(j<0) j=((j+n)%n+n)%n; if(vis[j][i]){ dp[i]=min(dp[i],dp[j]+dis[i][j]); } if(j==st) break; } } for(int i=st+1;;i++){ if(i>=n) i%=n; if(i==st) break; if(vis[i][st]) ans=min(ans,dp[i]+dis[i][st]); } } printf("%.2lf\n",ans); } return 0; }
相关文章推荐
- 最全的jquery datatables api 使用详解
- [LeetCode] Subsets
- 黑马程序员_Java面向对象
- isIsomorphic
- Python包RLPY初识(一)
- javascript-学习笔记-<script> </script> 代码执行的和上一个博客相对应的
- 帆布指纹识别——用户无隐私
- 05-图2. Saving James Bond - Easy Version (25)
- 汉罗塔lua实现
- android屏幕适配建议
- [LeetCode] Best Time to Buy and Sell Stock II
- PCIe学习记录
- java jdk查看源码
- 数据结构基础
- [LeetCode] Best Time to Buy and Sell Stock
- Java反射技术一:基本知识点
- hdu 1789 排序+数组标记
- html页面元素加载顺序
- REST聊天应用升级——妖哲开始打通后端6
- 基于TCP的通信 客户端