您的位置:首页 > 其它

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,因此要找出面积非零的最小周长三角形

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: