程序设计作业week03
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。不熟不熟还需努力。
- 点赞
- 收藏
- 分享
- 文章举报
- 面向对象的程序设计_第一次作业 3月12日
- 数据结构第一次作业:程序设计技术规则
- 面向对象程序设计 第三次作业补充
- 面向对象程序设计课-第三次作业(改)
- 现代程序设计 作业 2
- 数据结构与程序设计作业5
- 课堂在线Java程序设计作业 求斐波那契数
- 程序设计与算法(一)C语言程序设计CAP 第二周编程作业
- 面向对象程序设计 (C++语言描述)第一章课后习题作业
- 程序设计第二次作业<2>
- Linux程序设计作业1
- POJ C++程序设计 编程题#1 编程作业—运算符重载
- 程序设计作业报告项目四——“撞错”体验
- 团队作业-第四周-面向对象程序设计
- 程序设计作业报告项目三(1)
- 程序设计作业报告模板
- POJ C++程序设计 编程作业—类和对象 编程题#3
- 第二次C程序设计作业
- 第二次C程序设计作业
- C程序设计课程-2012电子信息 第四堂课后作业