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);
    }
};
原文地址:https://www.cnblogs.com/litstrong/p/3030990.html