UVA - 10641(dp)

来源:互联网 发布:2016年网络词汇 编辑:程序博客网 时间:2024/06/04 19:57

本题目是给定一个n(n<=30)边的凸多边形,然后给定m(m<=1000)个外围的灯的坐标和安装每个灯的费用,求用最少费用照亮所有边。


因为是凸多边形,很容易想到,把每个灯所能照亮的范围预处理成一个连续的区间,然后排序,用背包时选择就可以了。

不过有一点不同的是这里所要照亮的不是一条直线而是一个环状,所以应该从任意一个点为起始点,然后选择最优方案去包围点。

因为环状处理很经典,展示代码。

另外判断一个灯是否可以照亮一条特定的边的方法是:该灯与凸多边形的核心在边的两侧。

#include <cmath>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define rep(i,n) for(int i=0;i<n;i++)#define rep1(i,x,n) for(int i=x;i<=n;i++)using namespace std;struct point{  double x,y,val;  point(double x=0,double y=0,double z=0):x(x),y(y),val(z){}  bool operator<(const point& a)const{    if(x!=a.x) return x<a.x;    return y<a.y;  }}col;double cross(point a,point b){  return a.x*b.y-a.y*b.x;}point operator-(point a,point b){  return point(a.x-b.x,a.y-b.y);}int judge(point A,point a,point b){  return cross(A-a,b-a)*cross(col-a,b-a)<0;}const int N = 2111;point pol[N],a[N],b[N];int n,m;int init(){  for(int i=1;i<=m;i++){      if(judge(a[i],pol[n],pol[n+1])){         int l=n,r=n+1;         while(judge(a[i],pol[l-1],pol[l])) l--;         while(judge(a[i],pol[r],pol[r+1])) r++;         b[i]=point(l,r,a[i].val);      }      else{         rep1(j,1,n){            if(judge(a[i],pol[j],pol[j+1])){               int l=j,r=j+1;               while(judge(a[i],pol[r],pol[r+1])) r++;               b[i]=point(l,r,a[i].val);               break;            }         }      }  }  sort(b+1,b+1+m);}typedef long long LL;const LL inf = 1e12;LL d[N][70],s,vis[N][70];LL dp(int i,int j){  if(vis[i][j])  return d[i][j];  vis[i][j]=1;  if(j>=s+n) return d[i][j]=0;  if(i==m+1) return d[i][j]=inf;  d[i][j] = inf;  d[i][j] = min(dp(i+1,j),d[i][j]);  if(b[i].y>j && b[i].x<=j)     d[i][j] = min(d[i][j],dp(i+1,b[i].y)+(int)b[i].val);  return d[i][j];}int solve(){    long long res=inf;    for(int i=1;i<=n;i++){        s=i;        memset(vis,0,sizeof(vis));        res=min((LL)res,dp(1,s));    }    if(res==inf) printf("Impossible.\n");    else printf("%lld\n",res);}int main(){    while(scanf("%d",&n)==1 && n){       col.x=col.y=0;       rep1(i,1,n) {          scanf("%lf %lf",&pol[i].x,&pol[i].y);          col.x+=pol[i].x;          col.y+=pol[i].y;          pol[i+n]=pol[i];       }       col.x/=n,col.y/=n;       scanf("%d",&m);       rep1(i,1,m) scanf("%lf %lf %lf",&a[i].x,&a[i].y,&a[i].val);       init();       solve();    }    return 0;}



0 0
原创粉丝点击