dfs暴力,可以过N=18
的三个点,15分。
主要思想:反过来思考,对18个区间进行枚举,每个区间选或不选两种情况,看一共能组成多少个不同的区间,组成的区间个数即为答案。
// 15分 dfs暴力
#include <iostream>
#include <cstring>
#include <algorithm>
#include <unordered_set>
#include <vector>
#define x first
#define y second
using namespace std;
typedef pair<int, int> PII;
const int N = 53;
int n, m;
PII a[N];
bool st[N];
int res;
vector<PII> ans;
//unordered_set<PII> ans; // 需要自定义哈希函数才能存 pair
// 枚举选或不选
void dfs(int u)
{
if (u == m)
{
int cnt = 0;
int l, r;
// 判断只有一段连续的区间 000XXXXX00
for (int i = 0; i <= n; i ++ )
{
if (st[i] != st[i + 1])
{
cnt ++ ;
if (st[i] == false && st[i + 1] == true) l = i + 1; // 左端点
if (st[i] == true && st[i + 1] == false) r = i; // 右端点
}
}
if (cnt == 2)
{
bool flag = true;
for (int i = 0; i < ans.size(); i++)
{
// 之前没有得到过这个区间,才计数,并加入
if (ans[i].x == l && ans[i].y == r)
{
flag = false;
break;
}
}
if (flag)
{
res ++ ;
ans.push_back({
l, r});
}
}
}
else
{
dfs(u + 1); // 不选
// 选
vector<int> temp;
int x1 = a[u].x, y1 = a[u].y;
for (int i = x1; i <= y1; i ++ )
if (!st[i])
temp.push_back(i);
for (auto i: temp) st[i] = true; // 标记
dfs(u + 1);
for (auto i: temp) st[i] = false; // 还原
}
}
int main()
{
cin >> n >> m;
for (int i = 0; i < m; i ++ )
{
int x, y;
cin >> x >> y;
a[i].x = x, a[i].y = y;
}
dfs(0);
cout << res << endl;
return 0;
}
/*
8 5
1 2
3 4
2 3
5 8
4 5
8 1
5 8
*/