[Uva10641]Barisal Stadium(区间dp)

题意:按照顺时针给出操场的周边点,然后给出周围可以建设照明灯的位置,以及在该位置建设照明灯的代价,照明灯照射的范围与操场的边界相切,现在要求一个最小的花费,要求操场的所有边都被照射到。

解题关键:预处理每台灯能够覆盖到的范围,然后对环进行dp即可。对环进行dp的方法是枚举起点,覆盖所有点即可。

注意用叉积的方法处理灯能否照到某条边->某个点。

$dp[i][j]$表示从第$i$个点到第$j$个点之间的边都被照射到的最小代价,只要有某个等得照射范围有覆盖到$i$,$j$,就可以向外扩展。

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const double eps=1e-8;
const int N=105;  
const int M=1005;  
int n,m,dp[N];  
bool flag[N];
struct Point{  
    double x,y;  
    Point(double x=0,double y=0) {  
        this->x=x;  
        this->y=y;  
    }
    void read(){  
        scanf("%lf%lf",&x,&y);  
    }
}p[N],o;
  
struct node{  
    int l,r,c;
}q[M];

bool judge(Point p0, Point p1, Point p2) {  
    return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y)<-eps;//叉积判断是否能被照到 
}

node tra(Point t, int c){  
    node ans;  
    ans.c=c;
    memset(flag,0,sizeof flag);  
    for(int i=0;i<n;i++) if(judge(t,p[i],p[i+1]))  flag[i]=true;
    if (flag[0]&&flag[n-1]){  
        int l=n-1,r=0;
        while(flag[l-1]) l--;  
        while(flag[r+1]) r++;  
        ans.l=l,ans.r=r+n;
    }
    else{  
        int l=0,r=n-1;  
        while(!flag[l]) l++;
        while(!flag[r]) r--;
        ans.l=l,ans.r=r;  
    }
    return ans;  
}  
  
bool solve(){  
    int ans=inf; 
    for(int i=0;i<n;i++){  
        fill(dp,dp+2*n+1,inf);
        dp[i]=0;
        for(int j=0;j<n;j++){
            int r=i+j;  
            for(int k=0;k<m;k++){
                if(q[k].l>r) continue;
                int now=min(i+n,q[k].r+1);  
                dp[now]=min(dp[now],dp[r]+q[k].c);  
            }  
        }  
        ans=min(ans,dp[i+n]);
    }
    if(ans==inf) return false;
    printf("%d
",ans);
    return true;
}  
  
int main(){  
    while(~scanf("%d",&n)&&n){
        for(int i=0;i<n;i++) p[i].read();  
        p[n]=p[0];
        scanf("%d",&m);  
        Point tmp;  
        int c;  
        for(int i=0;i<m;i++){  
            tmp.read();
            scanf("%d",&c);  
            q[i]=tra(tmp,c);  
        }
        if (!solve()) printf("Impossible.
");  
    }  
    return 0;  
}  
原文地址:https://www.cnblogs.com/elpsycongroo/p/7808858.html