CodeForces 385 D.Bear and Floodlight(状压DP+计算几何)

85 篇文章 0 订阅
40 篇文章 1 订阅

Description
二维平面上有n个探照灯,第i个灯在(xi,yi)出,且可以照亮任意a[i]度角的范围,问这n个灯最多可照亮x轴上区间[l,r]区域从l开始被照亮的连续的最长长度
Input
第一行三个整数n,l,r表示灯的数量和要照亮的范围,之后n行每行三个整数xi,yi,ai分别表示第i个灯的二维坐标和照亮的范围(1<=n<=20,-1e5<=l<=r<=1e5,-1000<=xi<=1000,1<=yi<=1000,1<=ai<=90)
Output
输出[l,r]区域从l开始被照亮的连续的最长长度
Sample Input
2 3 5
3 1 45
5 1 45
Sample Output
2.000000000
Solution
状压DP,一个状态i表示亮灯的集合,i的二进制表示中第j位是1表示第j个灯亮,否则不亮,dp[i]表示i状态最多可以照亮的连续区域长度,转移方程为dp[i&(1 << j)]=max(dp[i&(1 << j)],dp[i]+deal(dp[i],j)),其中i&(1 << j)=0表示第j个灯不在i状态中然后把第j个灯的照射范围放在最右边,deal(dp[i],j)求出第j个灯从dp[i]位置开始照可以照多长的距离,最终dp[(1 << n)-1]即为答案
Code

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
#define INF 0x3f3f3f3f
#define maxn (1<<20)
double l,r,x[20],y[20],a[20],dp[maxn];
int n;
double deal(double x0,int i)
{
    double temp=atan((r-x[i])/y[i]);
    temp=min(temp,atan((x0-x[i])/y[i])+a[i]);
    return x[i]+y[i]*tan(temp);
}
int main()
{
    while(~scanf("%d%lf%lf",&n,&l,&r))
    {
        r-=l;
        for(int i=0;i<n;i++)scanf("%lf%lf%lf",&x[i],&y[i],&a[i]),x[i]-=l,a[i]=a[i]/180.*acos(-1.0);
        memset(dp,0,sizeof(dp));
        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)],deal(dp[i],j));
        printf("%.10f\n",dp[N-1]);
    }   
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值