uva 1425 - Metal(递推)

来源:互联网 发布:linux 授权目录给用户 编辑:程序博客网 时间:2024/05/04 10:02

题目链接:uva 1425 - Metal

题目大意:现在要用如图机器对一块钢板进行切割,给出切割路线经过的若干个点,问可以切割成多少种不同的形状,注意切割下的为一整块。

解题思路:

  • 由图可以得知,两条切割线是不可以相交的
  • 由题目描述可知,所有点的x坐标是不会重复的
  • 机器不会回退,也就是说钢板是朝一个方向移动的,这样的切割路线是不会产生的

所以我们定义两条切割线分别为上线和下线,两条折线不能相交,dp[i][j]表示上线画到点i,下线画到点j的切割方法数。因为所给定得点都需要被切割,将点按照x排序,然后递推。

  • dp[i][j]+=dp[i1][j]
  • dp[j][i]+=dp[j][i1]
    因为点i-1的横坐标肯定大于j,所以肯定可以转移。
  • dp[i][i1]+=dp[j][i1]
  • dp[i1][i]+=dp[i1][j]
    这种情况下,j的横坐标是小于x-1的横坐标,所以有可能发生相交的情况。(红线为上线,蓝线为下线)

所以需要进行判断,绿线为需要判定的线,需要考虑到所有在上线的点[j+1,i1](紫色点),均要在对应横坐标相同的褐色点上面,同理判断上线的时候要在下面。

#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int N = 55;const double eps = 1e-9;struct point {    double x, y;}p[N];int n, dp[N][N];bool cmp (const point& a, const point& b) {    return a.x < b.x;}bool judge (int a, int b, double d, int key) {    for (int i = a + 1; i <= b; i++) {        double tmp = p[a].y + d * (p[i].x - p[a].x);        if (key == 0 && tmp - p[i].y > -eps)            return false;        if (key == 1 && tmp - p[i].y < eps)            return false;    }    return true;}int solve () {    memset(dp, 0, sizeof(dp));    dp[1][0] = dp[0][1] = 1;    for (int i = 2; i < n-1; i++) {        int u = i-1;        for (int j = 0; j < u; j++) {            dp[i][j] += dp[u][j];            dp[j][i] += dp[j][u];            double xi = p[i].x - p[j].x;            double yi = p[i].y - p[j].y;            double d = yi / xi;            if (judge(j, u, d, 0))                dp[u][i] += dp[u][j];            if (judge(j, u, d, 1))                dp[i][u] += dp[j][u];        }    }    /*    for (int i = 0; i < n; i++) {        for (int j = 0; j < n; j++) {            if (dp[i][j] && (i == n-2 || j == n-2)) {                printf("%d %d: %d\n", i, j, dp[i][j]);            }        }    }    */    int ans = 0, u = n-1;    for (int i = 0; i < u-1; i++) {        double xi = p[u].x - p[i].x;        double yi = p[u].y - p[i].y;        double d = yi / xi;        if (judge(i, u-1, d, 0))            ans += dp[u-1][i];        if (judge(i, u-1, d, 1))            ans += dp[i][u-1];    }    return ans;}int main () {    int cas;    scanf("%d", &cas);    while (cas--) {        scanf("%d", &n);        for (int i = 0; i < n; i++)            scanf("%lf%lf", &p[i].x, &p[i].y);        sort(p, p + n, cmp);        printf("%d\n", solve());    }    return 0;}
4 3
原创粉丝点击