区间问题 AcWing 905. 区间选点 AcWing 908. 最大不相交区间数量

AcWing 905. 区间选点

原题链接

AcWing 905. 区间选点
在这里插入图片描述

样例解释

在这里插入图片描述
选择1, 4 即可

算法标签

贪心

思路

1.将每个区间按右端点从小到大排序
2.从前往后依次枚举每个区间
如果当前区间中已经包含点,则直接pass ;
否则,选择当前区间的右端点

证明

设每个区间内至少包含一个选出的点。选择的点的数量所组成集合为 c n t cnt cnt
选择的点的最小数量为 a n s ans ans
a n s < = c n t ans<=cnt ans<=cnt
由于选择
根据选择策略 – 如果当前区间中已经包含点,则直接pass ;否则,选择当前区间的右端点
因此 所得cnt值实际为相互之间没有交集的区间个数。依题意,使得每个区间内至少包含一个选出的点,至少需要cnt个点。
a n s > = c n t ans>=cnt ans>=cnt
因此 a n s = c n t ans=cnt ans=cnt

代码

#include<bits/stdc++.h>
#define int long long
#define rep(i, a, b) for(int i=a;i<b;++i)
#define Rep(i, a, b) for(int i=a;i>b;--i)
using namespace std;
const int N = 100005;
inline int read(){
   int s=0,w=1;
   char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
   while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
   return s*w;
}
void put(int x) {
    if(x<0) putchar('-'),x=-x;
    if(x>=10) put(x/10);
    putchar(x%10^48);
}
struct sec{
    int l, r;
}ses[N];
bool cmp(sec A, sec B){
    return A.r<B.r;
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int n=read();
	rep(i, 0, n){
	    ses[i].l=read(), ses[i].r=read();
	}
	sort(ses, ses+n,cmp);
	int ans=1;
	int t=0;
	rep(i, 1, n){
	    if(ses[t].r>=ses[i].l&&ses[t].r<=ses[i].r){
	       continue;
	    }else{
	        t=i;
	        ans++;
	    }
	}
	printf("%lld\n", ans);
	return 0;
}

由于cnt值实际为相互之间没有交集的区间个数
因此该题与下题所求一致

AcWing 908.最大不相交区间数量

原题链接

Acwing908. 最大不相交区间数量
代码一致

原创不易
转载请标明出处
如果对你有所帮助 别忘啦点赞支持哈
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
最大团问题是指在一个无向图中找到一个最大的完全子图,其中任意两个节点都有边相连。采用分支限界法可以有效地解决最大团问题。 具体步骤如下: 1. 定义一个数据结构,记录当前搜索到的最大团大小、当前已定的点集以及剩余可点集。 2. 从剩余可点集中择一个点,将其加入当前已定的点集中,并更新当前最大团大小。 3. 对于每个新加入的点,将其与已定的点集中的所有点进行比较,找到与其相连的点,并将其从剩余可点集中删除。 4. 递归搜索剩余可点集中的点,重复执行步骤2和3,直到剩余可点集为空。 5. 如果当前已定的点集大小大于当前最大团大小,则更新最大团大小,并保存当前已定点集。 6. 回溯到上一层,将已择的点从当前已定点集中删除,重新加入剩余可点集中,继续搜索。 7. 最终得到的最大团即为所求。 以下是C语言代码实现: ```c #include <stdio.h> #include <stdlib.h> #include <stdbool.h> #define MAXN 100 // 最大点数 int graph[MAXN][MAXN]; // 图的邻接矩阵 int n, max_clique; // 点数、最大团大小 bool is_clique[MAXN]; // 当前最大团包含的点集 void dfs(int cur_node, int cur_clique_size, int rest_nodes[], int rest_nodes_size) { if (rest_nodes_size == 0) { if (cur_clique_size > max_clique) { max_clique = cur_clique_size; for (int i = 0; i < n; i++) { is_clique[i] = false; } for (int i = 0; i < cur_clique_size; i++) { is_clique[rest_nodes[i]] = true; } } return; } if (cur_clique_size + rest_nodes_size <= max_clique) { // 剪枝 return; } int new_rest_nodes[MAXN], new_rest_nodes_size = 0; for (int i = 0; i < rest_nodes_size; i++) { int next_node = rest_nodes[i]; if (graph[cur_node][next_node]) { new_rest_nodes[new_rest_nodes_size++] = next_node; } } dfs(cur_node + 1, cur_clique_size, new_rest_nodes, new_rest_nodes_size); // 不择当前节点 rest_nodes[cur_clique_size] = cur_node; dfs(cur_node + 1, cur_clique_size + 1, rest_nodes, cur_clique_size); // 择当前节点 } int main() { scanf("%d", &n); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { scanf("%d", &graph[i][j]); } } int rest_nodes[MAXN], rest_nodes_size = n; for (int i = 0; i < n; i++) { rest_nodes[i] = i; } max_clique = 1; dfs(0, 0, rest_nodes, rest_nodes_size); printf("Max clique size: %d\n", max_clique); printf("Nodes in the clique: "); for (int i = 0; i < n; i++) { if (is_clique[i]) { printf("%d ", i); } } printf("\n"); return 0; } ``` 该算法的时间复杂度为O(2^n),因为在最坏情况下需要搜索整个指数级的状态空间。但是,由于采用了剪枝策略,实际运行效率要高于暴力枚举。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

飞滕人生TYF

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值