题面见这,给一个多边形,有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); } };