CCF-CSP 29次 第五题【202303-5 施肥】15分题解

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
*/ 

猜你喜欢

转载自blog.csdn.net/qq_51879318/article/details/130293232