CodeForces 385D: Bear and Floodlight
类型:DP,计算几何
题意:坐标系上有(l,0)~(r,0)一条直线,是一条路。然后还有其他一些点,这些点上有灯,灯能照一定的角度,需要用这些灯照亮那条路,问起点开始最远一直能照到哪。
思路:
状态压缩DP.
dp[1111..1] = max(遍历所有灯,那个被去掉的灯,从dp[11..0..11]这点开始照,最远照到哪)
就是求计算几何有点不会诶。。。。
与出现顺序有关的问题,可以用状态DP,从N!降到2N。
我的代码:
#include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define N 22 const double eps = 1e-8; const double PI = acos(-1); double dp[1<<21]; int x[N], y[N], a[N]; int n, l, r; struct Point { Point(){} Point(double a,double b):x(a),y(b){} double x, y; Point operator - (const Point &b) const { return Point(x-b.x, y-b.y); } void print(char str[]) { printf("%s %lf %lf\n",str, x, y); } }point[N]; Point rotate (Point p, double a) const { a = a/180.0 * PI; return Point(p.x*cos(a) - p.y*sin(a), p.x*sin(a) + p.y*cos(a)); } double cal(double now, int i) { //printf("i = %d ", i); //printf("now = %lf\n", now); Point to = Point(now, 0) - point[i]; to = to.rotate(a[i]); //printf("to = (%lf,%lf)\n", to.x, to.y); if (to.y > -eps) return r; else return min(point[i].x + point[i].y * (to.x / -to.y), r+0.0); } int main() { while (~scanf("%d%d%d", &n, &l, &r)) { for (int i = 0; i < n; i++) { scanf("%lf%lf%d", &point[i].x, &point[i].y, &a[i]); //printf("%lf %lf %d\n",point[i].x, point[i].y, a[i]); } dp[0] = l; for (int i = 1; i < (1<<n); i++) { dp[i] = l; for (int j = 0; j < n; j++) { if ((i&(1<<j))) { dp[i] = max(dp[i], cal(dp[(i&(~(1<<j)))], j)); } } //printf("%d: %lf\n", i, dp[i]); } printf("%.8lf\n", dp[(1<<n)-1]-l); } return 0; }
posted on 2014-03-05 21:44 ShineCheng 阅读(204) 评论(0) 编辑 收藏 举报