uva 10641

来源:互联网 发布:mac os系统在哪下载 编辑:程序博客网 时间:2024/05/17 08:52

动态规划,同时又涉及到几何的一些知识。首先对于输入的那些顶点数据求出对应的多边形的中心,然后利用叉乘的符号判断对应的光源的点是否能够照射到对应的边,判断完所有的边之后就记录该光源点能够照射的范围,这里出现了一个技巧在于由于这个多边形是环状的,但是我们在处理环形的时候是把多边形的边数变为原来的两倍,也就是说,多边形的边的实际编号为0到N-1,从后面开始,N就代表着第0条边,N+1就代表着第1条边,以此类推,这样做是为了便于后面动态规划的处理。

在上面的处理全部都结束的时候,我们分别从第1条边一直到第N条边开始进行动态规划的操作,从当前的边i开始,偏移j作为起始边,判断是否能够有光源照到当前的起始边,如果可以就对最后能照到的那条边的代价之和进行更新,并且要记录所有情况的最优值,具体实现见如下代码:

#include<iostream>#include<vector>#include<string>#include<set>#include<stack>#include<queue>#include<map>#include<algorithm>#include<cmath>#include<iomanip>#include<cstring>#include<sstream>#include<cstdio>#include<deque>using namespace std;const double eps = 1e-6;const int Inf = 1<<30;class Point{public:double x, y;int left, right;//供light使用int cost;Point(double x = 0, double y = 0, int cost = 0){this->x = x;this->y = y;this->cost = cost;}Point Sub(Point a){return Point(x - a.x, y - a.y);}double mulCross(Point a){return (x*a.y-y*a.x);}};Point center;//多边形的中心点class Solve{public:int N, M;//多边形的顶点个数 光源的个数Point vert[35];Point light[1010];int ans;int judge(double t1,double t2){if (t1*t2 < -eps) return -1;return t1*t2 > eps;}void getEdge(int ind){bool flag[35];memset(flag, false, sizeof(flag));for (int i = 0; i < N; i++){Point ab = vert[i + 1].Sub(vert[i]);Point ao = center.Sub(vert[i]);Point ai = light[ind].Sub(vert[i]);double t1 = ab.mulCross(ao);double t2 = ab.mulCross(ai);if (judge(t1, t2) < 0) flag[i] = true;}if (flag[0] && flag[N - 1]){int left = N - 1, right = N;while (flag[left]){light[ind].left = left;left--;}while (flag[right-N]){light[ind].right = right;right++;}}else{int left = 0, right = N - 1;while (!flag[left]) left++;light[ind].left = left;while (!flag[right]) right--;light[ind].right = right;}light[ind].right++;//左闭右开if (light[ind].right < light[ind].left)light[ind].right += N;}void Deal(){for (int i = 0; i < M; i++)getEdge(i);ans = Inf;int dp[70];for (int i = 0; i < N; i++){for (int m = 0; m < 70; m++) dp[m] = Inf;dp[i] = 0;for (int j = 0; j < N; j++){int t = i + j;for (int k = 0; k < M; k++){if (light[k].left > t) continue;int ind = min(light[k].right, i + N);dp[ind] = min(dp[ind], light[k].cost + dp[t]);}}ans = min(ans, dp[i + N]);}if (ans == Inf) cout << "Impossible.\n";else cout << ans << endl;}};int main(){Solve a;while (cin >> a.N){if (a.N == 0) break;center.x = center.y = 0;for (int i = 0; i < a.N; i++){cin >> a.vert[i].x >> a.vert[i].y;center.x += a.vert[i].x;center.y += a.vert[i].y;}a.vert[a.N] = a.vert[0];center.x = center.x / a.N;center.y = center.y / a.N;cin >> a.M;for (int i = 0; i < a.M; i++)cin >> a.light[i].x >> a.light[i].y >> a.light[i].cost;a.Deal();}return 0;}


原创粉丝点击