CodeForces 385D Bear and Floodlight

来源:互联网 发布:js获取input上传文件 编辑:程序博客网 时间:2024/04/28 01:00

题意:

从坐标(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;}


0 0
原创粉丝点击