SRM 574 DIV1 L2

题面见,给一个多边形,有N个顶点,依次连接多边形上的顶点,要求每条线段要至少与之前的某条线段相交,且最终回到原点,求全部的方案数。需要发现具体的方案数与之前的访问的点的顺序是没有关系的,和具体的集合是有关系的,采用动态规划解决该问题。

#include <iostream>

#include <algorithm>

#include <vector>

#include <string>

using namespace std;

const int M = 18;



long long dp[1 << M][M];



bool check(int mask, int p, int q, int N) {

    if (p > q) {

        swap(p, q);

    }

    int part1 = ((1 << (q - p - 1)) - 1) << (p + 1);

    int part2 = (1 << N) - 1 - part1 - (1 << p) - (1 << q);

    //cout << mask << ", " << p << ", " << q << ", " << part1 << ", " << part2 << endl;

    return (mask & part1) && (mask & part2);

}



long long go(int mask, int b, int p, int N) {

    if (dp[mask][p] != -1) {

        return dp[mask][p];

    }

    

    if (mask == (1 << N) - 1) {

        //cout << check(mask, b, p, N) << ", " << b << ", " << p << endl;

        return check(mask, b, p, N) ? 1 : 0;

        //cout << "hi";

        //return 1;

    }    

    

    dp[mask][p] = 0;

    for (int i = 0; i < N; i++) {

        if (!(mask & (1 << i))) {

            //cout << "mask = " << mask << "; i = " << i << endl;

            if (check(mask | (1 << i), p, i, N)) {

                //cout << "dfs";

                dp[mask][p] += go(mask | (1 << i), b, i, N);

            }

        }

    }

    

    //cout << "mask = " << mask << ", p = " << p << ", dp = " << dp[mask][p] << endl;

    return dp[mask][p];

}





class PolygonTraversal {

public:

    long long count(int N, vector <int> points) {

        int mask = 0;

        for (int i = 0; i < points.size(); i++) {

            mask |= (1 << (points[i] - 1));

        }

        memset(dp, -1, sizeof(dp));

        //cout << "begin mask = " << mask << endl;

        return go(mask, points[0] - 1, points[points.size() - 1] - 1, N);

    }

};

 

你可能感兴趣的:(div)