题目:http://community.topcoder.com/stat?c=problem_statement&pm=12477&rd=15494
参考:http://apps.topcoder.com/wiki/display/tc/SRM+574
与上一题一样,只是限制条件变成了18,不能再用暴力法了,必须使用dp。
注意位操作,之前在isIntersect()函数中把 if ( mask & (1 << i) ) 写成了 if (mask >> i) ,这个bug调了很久才调出来。
代码:
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <bitset>
#include <string>
#include <vector>
#include <stack>
#include <deque>
#include <queue>
#include <set>
#include <map>
#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <cmath>
#include <cstring>
#include <ctime>
#include <climits>
using namespace std;
#define CHECKTIME() printf("%.2lf\n", (double)clock() / CLOCKS_PER_SEC)
typedef pair<int, int> pii;
typedef long long llong;
typedef pair<llong, llong> pll;
#define mkp make_pair
/*************** Program Begin **********************/
long long dp[1 << 18][18];
class PolygonTraversal {
public:
int N, start, end;
inline int addPoint(int mask, int p)
{
return ( mask | (1 << p) );
}
bool isIntersect(int mask, int p1, int p2)
{
bool f1 = false, f2 = false;
if (p1 > p2) {
swap(p1, p2);
}
for (int i = 0; i < N; i++) {
if ( mask & (1 << i) ) {
if (i > p1 && i < p2) {
f1 = true;
} else if (i < p1 || i > p2) {
f2 = true;
}
}
}
return f1 && f2;
}
long long rec(int mask, int p)
{
long long & res = dp[mask][p];
if (res != -1) {
return res;
}
if (mask == end) { // base case
if (isIntersect(mask, p, start) ) {
res = 1;
return 1;
} else {
res = 0;
return 0;
}
}
res = 0;
for (int i = 0; i < N; i++) {
if ( !( mask & (1 << i) ) ) { // 若点未访问
if (isIntersect(mask, p, i)) {
// 若符合,加入该点
res += rec( addPoint(mask, i), i );
}
}
}
return res;
}
long long count(int N, vector <int> points) {
long long res = 0;
this->N = N;
end = (1 << N) - 1;
start = points[0] - 1;
int mask = 0;
for (int i = 0; i < points.size(); i++) {
--points[i];
mask = addPoint(mask, points[i]);
}
memset(dp, -1, sizeof(dp));
res = rec(mask, points[ points.size() - 1 ]);
return res;
}
};
/************** Program End ************************/