Week3作业

A题 选数问题

题目描述

Given [Math Processing Error] positive numbers, ZJM can select exactly [Math Processing Error] of them that sums to [Math Processing Error]. Now ZJM wonders how many ways to get it!
input:
The first line, an integer [Math Processing Error], indicates the number of test cases. For each case, there are two lines. The first line, three integers indicate [Math Processing Error], [Math Processing Error] and [Math Processing Error]. The second line, [Math Processing Error] integers indicate the positive numbers.
output:
For each case, an integer indicate the answer in a independent line.

思路

这里将所有的数都存进一个数组,这个数组进行dfs递归操作,当递归k次后判断是否是正确,在k次之前就已经大于S就应该提前结束递归节省时间

代码
#include<iostream>
using namespace std;
int n,K,S,ans;
int a[100];


void dfs(int k,int sum,int end)
{
	if(sum>S)return;//提前退出 
	if(k==K)
	{
		if(sum==S) ans++;
	}
	else 
	{
		for(int i=end;i<n;i++)
			dfs(k+1,sum+a[i],i+1);
	}
}

int main()
{
	int T;
	cin>>T;
	while(T--)
	{
		cin>>n>>K>>S;
		for(int i=0;i<n;i++)
			cin>>a[i];
		ans=0;
		dfs(0,0,0);
		cout<<ans<<endl;
		
	}
	return 0;
}

总结

这次的作业我有罪啊,因为贪玩加上不注意看群里的通知,等到这次作业结束才发觉不对劲,o(╥﹏╥)o。

B题 区间选点

题目描述

数轴上有 n 个闭区间 [a_i, b_i]。取尽量少的点,使得每个区间内都至少有一个点(不同区间内含的点可以是同一个)
输入:
第一行1个整数N(N<=100)
第2~N+1行,每行两个整数a,b(a,b<=100)
输出:
一个整数,代表选点的数目

思路

这道题的题意很明确,这里我采用这样的贪心准则,取剩余区间中右节点最小的,用其左节点与基准点即之前选出的区间的右节点进行比较,如何小于右节点就可以共用一个点,否则就更新基准点为新区间的右节点。这里将所有的区间用右节点进行非递减排序,依次从中取元素。

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

struct mm
{
	int l,r;
	mm(){};
	mm(int a,int b):l(a),r(b){};
	bool operator<(const mm&p)
	{
		return r<p.r;
	}
};
mm shu[101];
int n;
int main()
{
	cin>>n;
	for(int i=0;i<n;i++)
	{
		cin>>shu[i].l>>shu[i].r;
	}
	sort(shu,shu+n);
	int count=0,nowp=-1;
	for(int i=0;i<n;i++)
		if(shu[i].l>nowp)
		{
			nowp=shu[i].r;
			count++;
		}
	cout<<count<<endl;
	return 0;
}
总结

蒟蒻通过这道题可算是搞清楚了重载小于号还有cmp函数里小于号的小花招了,以下面cmp函数所示,a和b可以看做是数组中的前后两项,a<b也就表示排序后数组内的关系,本例为递增关系,而重载小于号时,调用的结构体或类可以看做为前者元素,函数内部表示和cmp函数一样,这里也是递增关系,菜鸡理解方式

	bool operator<(const mm&p)
	{
		return r<p.r;
	}
	
	bool cmp(const int &a,const int &b)
	{
    	return a<b;
	}

C题 区间覆盖

题目描述

数轴上有 n (1<=n<=25000)个闭区间 [ai, bi],选择尽量少的区间覆盖一条指定线段 [1, t]( 1<=t<=1,000,000)。
覆盖整点,即(1,2)+(3,4)可以覆盖(1,4)。
input:
第一行:N和T 表示给定区间数和所要覆盖的区间右端点值
第二行至N+1行: 每一行一个闭区间。
output:
选择的区间的数目,不可能办到输出-1

思路

我们这次采用左端点非递减顺序进行排列,对于每个记录的左端点值,都要从数组中找到一个元素其左端点小于等于当前记录的左端点值,并且右端点值尽可能大的区间进行更新,这样才会用尽可能少的区间覆盖整个区间。

代码
#include<iostream>
#include<stdio.h>
#include<algorithm>
using namespace std;

struct mm
{
	int l,r;
	bool operator<(const mm&p)
	{
		return l<p.l;
	}
};

mm shu[25002];
int n,T,S=1;
int main()
{
	scanf("%d%d",&n,&T); 
	for(int i=0;i<n;i++)
	{
		scanf("%d%d",&shu[i].l,&shu[i].r);
	}
	sort(shu,shu+n);
    int n_x=1,n_y=0,count=0;
    int i=0;
    while(n_x<=T&&i<n)
    {
		if(shu[i].l>n_x) break;
			bool flag = 0;
    	for(;i<n&&shu[i].l<=n_x;i++)
    	{
    		if(shu[i].r>n_y)
    		{
				n_y=shu[i].r;//更新最右值
				flag=1;
			}
		}
		if(flag)
		{
	      count++;
		  n_x=n_y+1;
		} 
    }
   	if(n_x>T) printf("%d\n",count);
	else printf("-1\n"); 
	return 0;
}

总结

开始没有考虑到flag的必要,对每次右端点值更新都进行count++造成结果很大,立一个flag表示更新了右值,这样就解决多次加一的问题。

发布了20 篇原创文章 · 获赞 3 · 访问量 457

猜你喜欢

转载自blog.csdn.net/qq_44893580/article/details/104978056