您的位置:首页 > 其它

程序设计作业week03

2020-03-10 01:14 141 查看

A - 选数问题

题目
样例
Input

110 3 10
1 2 3 4 5 6 7 8 9 10

Output

4

解题思路

选数问题可以用dfs解决,选择一个数向前继续探索,选下一个数,一旦发现不符合条件或者达到要求就返回,回溯到上一层,在上一层继续选择。

dfs
把可供选择的数都存在a数组里。定义函数dfs(int sum, int k, int j),sum为当前所选的数的和,初始值为0;k表示已经选了多少个数,初始值为0;j表示上一个加入的数的下标,初始值为0.

当k==K时,返回上一层。同时若这k个数的和正好是S,则解的个数++。否则从上一层所选的数字后面一个数a[j+1]开始遍历,选择数字a[i],然后递归dfs(sum+a[i], k+1, i+1)。

完整代码

#include <iostream>
using namespace std;
int T,K,n,S;
int cnt = 0;	//解的数量
int a[20];	//可选的数
void dfs(int sum, int k, int j)
{
if(k == K)
{
if(sum ==S)
cnt++;
return;
}
for(int i=j;i<n;i++)
{
dfs(sum+a[i], k+1, i+1);
//选数加和 计数加一 只往后开始选避免重复
}
}
int main()
{
cin>>T;
for(int i=0;i<T;i++)
{
cnt = 0;
cin>>n>>K>>S;
for(int j=0;j<n;j++)
cin>>a[j];
dfs(0, 0, 0);
cout<<cnt<<endl;
}
return 0;
}

B - 区间选点

题目
样例

Input

21 5
4 6

Output

1

Input

3
1 3
2 5
4 6

Output

2

解题思路

将所有的区间[a,b]按照b从小到大排序(b 相同时 a 从大到小排序)。排序使用sort函数,自定义cmp。

bool cmp(sec x, sec y)
{
if(x.b == y.b)	return x.a > y.a;
else return x.b < y.b;
}

首先选中最小的b0,数字b0可以满足任何[ ,b0]的区间。然后判断b0是否在区间[ ,b1]中,若在,则不用更新继续向后判断;若不在区间中,则更新b为b1,计数++。以此类推,遍历区间数组判断。

int ed = s[0].b;
int cnt = 1;
for(int i=1;i<n;i++)
{
if(ed < s[i].a)
{
ed = s[i].b;
cnt++;
}
}

完整代码

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

struct sec
{
int a, b;
}s[110];

bool cmp(sec x, sec y)
{
if(x.b == y.b)	return x.a > y.a;
else return x.b < y.b;
}
int main()
{
cin>>n;
for(int i=0;i<n;i++)
{
cin>>s[i].a>>s[i].b;
}
sort(s, s+n, cmp);
int ed = s[0].b;
int cnt = 1;
for(int i=1;i<n;i++)
{
if(ed < s[i].a)
{
ed = s[i].b;
cnt++;
}
}cout<<cnt<<endl;
return 0;
}

C - 区间覆盖

题目
样例

Input

3 10
1 7
3 6
6 10

Output

2

解题思路

将区间数组按 a 从小到大排序

bool cmp(sec x, sec y)
{
return x.a<y.a;
}

设初始选定区间为(1,1),遍历区间数组扩展区间。
循环的终止条件是已经覆盖到所求区间。循环时需要判断的情况较多。
若区间断开,即后续的区间左端点与已覆盖区间的右端点之差大于1,则不能做到,应该跳出循环输出-1;若没有断开则遍历后面的区间,如果有区间包含的情况则选择大区间并更新右端点。在遍历到最后一个区间时也要特殊判断,看是否到最后一个区间能覆盖所求区间。

完整代码

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int num, tt;
int ll, rr;
int i,j,cnt;
bool judge;
struct sec
{
int a, b;
}s[25100];
bool cmp(sec x, sec y)
{
return x.a<y.a;
}void init()
{
scanf("%d %d", &num, &tt);
for(int i=0;i<num;i++)
{
scanf("%d %d",&s[i].a,&s[i].b);
}
sort(s, s+num, cmp);
ll = 1;
rr = 1;
i = 0;
j = 0;
cnt = 0;
judge = 0;
}
void out_put(bool jd)
{
if(jd == 1)
printf("-1\n");
else
printf("%d\n", cnt);
}
int main()
{
init();
while(ll<=tt)
{
if(s[j].a>ll)
{
judge = 1;
break;
}
for(i=j;i<num;i++)
{
if(s[i].a<=ll && s[i].b>=rr)
rr = s[i].b;
else if(s[i].a>ll)
{
ll = rr + 1;
cnt++;
j = i;
break;
}
}
if(i == num)
{
cnt++;
if(rr<tt)
judge = 1;
break;
}
}
out_put(judge);
return 0;
}

这是一个感想

个人不是很会写递归hhhhh,之前把一些经典简单的dfs问题,比如迷宫八皇后单词接龙什么的写过一遍后感觉好了些,这里的A题就不是很难。B题和C题是有关区间的贪心问题,本菜第一次接触。这种题关键点在于对区间按一定方法进行排序,然后确定选择方案,感觉有点难,特别是C题orz。C题最开始在群里跟别人讨论了一段时间才捋清了思路,然后才开始写,最开始还因为某行代码在调试的时候改忘了给崩了qwq。不熟不熟还需努力。

  • 点赞
  • 收藏
  • 分享
  • 文章举报
mmwtcl_ 发布了3 篇原创文章 · 获赞 0 · 访问量 118 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: