Codeforces 385D - Bear and Floodlight

385D - Bear and Floodlight

思路:状态压缩dp+计算几何。

i表示亮灯的集合,i的二进制中1表示亮灯,0表示不亮灯。

dp[i]表示在i的亮灯情况下最大的可以照亮的长度。

状态转移方程:dp[i^(1<<j)]=max(dp[i^(1<<j)],cal(dp[i],j))。

其中i&(1 << j)=0表示第j个灯不在i状态中,然后把第j个灯的照射范围放在最右边,cal(dp[i],j)求出第j个灯从dp[i]位置开始照可以照多长的距离。

最终dp[(1 << n)-1]即为答案。

关于cal函数的计算,见下图(还有两种情况没有画):

代码:

 

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pb push_back
#define mem(a,b) memset((a),(b),sizeof(a))
#define pi acos(-1.0)
double x[20],y[20],a[20],dp[(1<<20)-1];
double l,r;
double cal(double x0,int i)
{
    double t1=atan((r-x[i])/y[i]);
    double t2=atan((x0-x[i])/y[i])+a[i];
    return x[i]+tan(min(t1,t2))*y[i];
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n;
    cin>>n>>l>>r;
    r-=l;
    for(int i=0;i<n;i++)
    {
        cin>>x[i]>>y[i]>>a[i];
        x[i]-=l;
        a[i]=a[i]/180.*pi;
    }
    
    int N=1<<n;
    for(int i=0;i<N;i++)
    {
        for(int j=0;j<n;j++)
        {
            if((i&(1<<j))==0)
            {
                dp[i^(1<<j)]=max(dp[i^(1<<j)],cal(dp[i],j));
            }
        }
    }
    cout<<fixed<<setprecision(10)<<dp[N-1]<<endl;
    return 0;
}

 

 

 

 

posted @ 2017-08-16 13:36  Wisdom+.+  阅读(252)  评论(0编辑  收藏  举报