CodeForces 385D Bear and Floodlight

47 篇文章 0 订阅
28 篇文章 0 订阅

题意:

从坐标(L,0)到坐标(R,0)直线行走  走过的地方必须被N盏灯里的至少1盏照亮  每盏灯有一个位置坐标  照亮方向任意且可照亮无限远  但只有一个固定的照明角度  求最远走多远


思路:

灯的数量只有20  这是突破口  可以状态压缩  用dp[i]表示i状态时走的距离  i的二进制形式中1表示对应灯亮

那么最后答案就是dp[(1<<n)-1]即所有灯全亮  状态转移  dp[i] = max( dp[i] , dp[j] + distance(j->i) )

实现时用bfs维护dp就好  计算distance可能有点麻烦(我分类讨论的)  详见代码func()函数


代码:

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
#define M 1100000
#define pi acos(-1)

double dp[M];
double u,v;
int qu[M],in[M];
struct light
{
	double x,y,dg;
}lt[21];
int n,l,r;

double func(double way,int id)
{
	double deg=atan(fabs(way+u-lt[id].x)/lt[id].y);
	if(lt[id].x-u>way)
	{
		if(lt[id].dg<deg)
		{
			deg=deg-lt[id].dg;
			return lt[id].x-u-tan(deg)*lt[id].y-way;
		}
		else
		{
			deg=lt[id].dg-deg;
			return tan(deg)*lt[id].y+lt[id].x-u-way;
		}
	}
	else
	{
		if(atan((v-lt[id].x)/lt[id].y)>deg+lt[id].dg)
			return tan(lt[id].dg+deg)*lt[id].y-(u+way-lt[id].x);
		else return v-u;
	}
}

int main()
{
	int i,now,to;
	scanf("%d%lf%lf",&n,&u,&v);
	for(i=0;i<n;i++)
	{
		scanf("%lf%lf%lf",<[i].x,<[i].y,<[i].dg);
		lt[i].dg=lt[i].dg/180*pi;
	}
	qu[0]=l=r=0;
	while(l<=r)
	{
		now=qu[l++];
		for(i=0;i<n;i++)
		{
			if(!(now&(1<<i)))
			{
				to=now|(1<<i);
				dp[to]=max(dp[to],dp[now]+func(dp[now],i));
				if(!in[to])
				{
					in[to]=1;
					qu[++r]=to;
				}
			}
		}
	}
	//for(i=0;i<(1<<n);i++) printf("%d %f\n",i,dp[i]);
	printf("%.9f\n",min(dp[(1<<n)-1],1.0*v-u));
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值