程序设计思维与实践 Week8 作业

A - 区间选点 II

题目:

给定一个数轴上的 n 个区间,要求在数轴上选取最少的点使得第 i 个区间 [ai, bi] 里至少有 ci 个点

使用差分约束系统的解法解决这道题
使用差分约束系统的解法解决这道题
使用差分约束系统的解法解决这道题
使用差分约束系统的解法解决这道题
使用差分约束系统的解法解决这道题

Input
输入第一行一个整数 n 表示区间的个数,接下来的 n 行,每一行两个用空格隔开的整数 a,b 表示区间的左右端点。1 <= n <= 500000 <= ai <= bi <= 50000 并且 1 <= ci <= bi - ai+1。

Output
输出一个整数表示最少选取的点的个数

思路:
这一题上一次做还是用的贪心,这一次则要使用差分约束来做这一题。使用差分来做的话首先需要做的就是分析里面的差分约束式子。令 sum[ i ]为0 - i的点的数目,则 “ [ai, bi] 里至少有 ci 个点 ” 这句话可转换为
sum[ bi ] - sum[ ai ]>= ci
又,对其中每一个点,有
0 <= sum[ i+1 ] - sum[ i ] <= 1
因此,依据上面的式子加以变形,我们就可以得到一组差分约束的不等式。然后再借用spfa和dijktra中松弛条件的特性,将不等式组转换为图,如:a - b<= c -> a <= b + c 说明b到a有一条权值为c的边。在根据不等式组构造出图以后,使用spfa或dijstra跑最长路。总区间最右端点到0点的距离即为最终结果。这里要注意的是ai可能为0,将所有点右移一位来确保不会出现数组越界的情况。

代码:

#include <stdio.h>
#include <string.h>
#include <vector>
#include <queue>
using namespace std;
int dis[50100];
int vis[50100];
struct node
{
   
	int element;
	int weight;
};
vector<node> G[50100]; 
void init()
{
   
	for(int i=0;i<50100;i++)
	{
   
		dis[i]=-1000;
		vis[i]=0;
	}
}
int main()
{
   
	init();
	int n;
	scanf("%d",&n);
	int maxP=0;
	for(int i=0;i<n;i++)
	{
   
		int x,y,z;
		scanf("%d %d %d",&x,&y,&z);
		x++;y++;
		node temp;
		if(y>maxP)
			maxP=y;
		temp.element=y;temp.weight=z;
		G[x-1].push_back(temp);
	}
	node temp;
	for(int j=0;j<maxP;j++)
	{
   
		temp.element=j+1;temp.weight=0;
		G[j].push_back(temp);
	}
	for(int j=1;j<=maxP;j++)
	{
   
		temp.element=j-1;temp.weight=-1;
		G[j].push_back(temp);
	}
	queue<int> q;
	q.push(0);
	dis[0]=0;
	vis[0]=1;
	while(!q.empty())
	{
   
		int tmp=q.front();
		q.pop();
		vis[tmp]=0
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值