作业3、4+CSP

本文介绍了CSP模拟题目,包括区间选点、区间覆盖和作业DDL恐惧问题,采用BFS、贪心算法和二分查找等方法解决。同时探讨了在面对数列和数组问题时如何利用二分查找和动态规划优化解决方案。
摘要由CSDN通过智能技术生成

Week3作业
A-选数问题
1.题意:给出N个正整数,问有多少种组合使得K个数相加为S。输入输出样例为:
Input
1 //表示有几组数
10 3 10 //分别是该组数的个数、每个组合里整数的个数、相加的和
1 2 3 4 5 6 7 8 9 10//该组数的成员
Output
4//结果,即有多少种组合

2.思路:对于此类子集枚举的问题,可使用bfs求解,同时为了提高代码效率避免超出运行时间,可以删去一些不必要的部分,比如sum<0或者选数个数大于k个时,直接结束循环。同时定义一个count来记录方案的种数,每当选数个数达到k且sum为0的时候(代码里是sum-a[j]),count就要加1。

3.代码:

#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string.h>
using namespace std;
int count,n;
int a[100];

void bfs(int i,int j,int k,int sum)
{
   
	if(i==k && sum==0)
	{
   
		count++;
		return;
	}
	else if(i>k ||j>n-1 ||sum<0) return;
	bfs(i,j+1,k,sum);
	bfs(i+1,j+1,k,sum-a[j]);
}

int main()
{
   
	int m,k,sum;
	cin>>m;
	for(int i=0;i<m;i++)
	{
   
		count=0;
		cin>>n>>k>>sum;
		for(int i=0;i<n;i++) cin>>a[i];
		bfs(0,0,k,sum);
		cout<<count<<endl;
	}
	return 0;
}

B-区间选点
1.题意:数轴上有n个闭区间。取尽量少的点,使每个区间都至少有一个点。

2.思路:为了比较方便的表示一个区间,可以使用一个结构体类型的数组,结构体中包含两个整数,分别表示该区间的左右端点;接着要判断两个区间是否有重合,先对区间进行排序,然后进行比较,若一个区间的右端点大于后一个区间的左端点,则这两个区间没有公共部分,点的数量加1,我这里还用了一个behand来记录每个区间的左端点并与其后面一个区间的右端点来比较,若满足(a[i].y<behand),则将a[i].x的值赋予behand,并进行下一轮比较,直至循环结束。

3.代码:

#include <iostream>
#include <algorithm>
using namespace std;

struct area
{
   
	int x,y;
}a[100];

bool spot(area a,area b)
{
   
	if(a.x!=b.x) return a.x>b.x;
	else return a.y<b.y; 
} 

int main()
{
   
	int n; cin>>n;
	for(int i=0;i<n;i++) cin>>a[i].x>>a[i].y;
	sort(a,a+n,spot);
	int num=1,behand=a[0].x;
	for(int i=1;i<n;i++)
	{
   
		if(a[i].y<behand)
		{
   
			behand=a[i].x;
			num++;
		}
	} 
	cout<<num<<endl;
	return 0;
}

C-区间覆盖
1.题意:数轴上有n个闭区间,选择尽量少的区间覆盖一条指定线段。覆盖整点,比如(1,2)+(3,4)可以覆盖(1,4)。无法办到,输出-1。

2.思路:本题开始的动态数组c[i]表示每个以i开始的线段中右端点的最大值,在确定区间[a,b]后,应将起点设置为b,使用贪心策略进行查找,直到到达右端点为止;int m=0,x;其中m表示最大值,x为取得最大值时的i,在循环过程中,若m小于上一个区间的右端点,则退出循环。

3.代码:

#include <iostream>
#include <cstring>
using namespace std;
int* c=new int[1000000]; 

int main()
{
   
    int N,T;
    while(scanf("%d%d",&N,&T)!=EOF)
	{
   
        for(int i=0;i<1000000;i++) c[i]=-1;
        for(int i=0;i<N;i++)
		{
   
            int a,b;
            scanf("%d%d",&a,&b);
            if(c[a]<b) c[a]=b;
        }
        
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值