Codeforces 385D

385D - Bear and Floodlight

题目大意:有一个人从( l , 0 ) 想走到 ( r , 0 ),有 n 盏路灯,位置为( xi , yi ),每盏路灯都有一个照射的角度ai

这个角度内的区间都被照亮,问你走之前任意调路灯的方向,这个人只能走路灯照亮的地方,问你他最多能往

r 方向走多少距离。

思路:本来我想的是才20盏灯直接枚举灯的顺序也不会超时的吧,复杂度才20!* 20 (ps:我错了我是猪,20!复杂度很高),

结果GG,T掉了,改成状态压缩就过了,状态压缩也跑了2000+ms。dp[ i ],表示 i 这个状态下的到达的最长距离。

dp[ ( 1 << n ) - 1 ]就是我们要用的答案,将一个路灯照亮的距离往上加的时候,用正弦定理计算距离。

#include<bits/stdc++.h>
using namespace std;
const double pi=acos(-1);
const int N=20;
int n;
double l,r,dp[1<<N];
struct lit
{
    double x,y,a;
}w[21];
double dis(double x1,double y1,double x2,double y2)
{
    double a=(x1-x2)*(x1-x2);
    double b=(y1-y2)*(y1-y2);
    return sqrt(a+b);
}
double work(double pre,int g)
{
    double d=dis(pre,0,w[g].x,w[g].y);
    double c=acos(fabs(w[g].x-pre)/d);
    if(w[g].x<pre) c=pi-c;
    c=pi-w[g].a-c;
    if(c<0)
    {
        printf("%.12f
",r);
        exit(0);
    }
    double len=d*sin(w[g].a)/sin(c);
    return min(r,pre+len);
}
int main()
{
    scanf("%d%lf%lf",&n,&l,&r);
    r-=l;
    for(int i=0;i<n;i++)
    {
        scanf("%lf%lf%lf",&w[i].x,&w[i].y,&w[i].a);
        w[i].x-=l;
        w[i].a=w[i].a/180.0*pi;
    }
    memset(dp,0,sizeof(dp));
    int up=1<<n;
    for(int i=0;i<up;i++)
    for(int j=0;j<n;j++)
    {
        if((i&(1<<j))==0) dp[i^(1<<j)]=max(dp[i^(1<<j)],work(dp[i],j));
    }
    printf("%.12f
",dp[up-1]);
    return 0;
}
View Code

ps:能状压就不要枚举!!!!!!!!

原文地址:https://www.cnblogs.com/CJLHY/p/7374986.html