程序设计思维与实践 Week3 作业
程序员文章站
2022-03-18 13:42:07
...
A-选数问题
题意:
n个数中选K个数,其和等于S的方案有多少个?
思路:
该题是典型的子集枚举问题,但需要对过程进行剪枝。当选数个数大于k或者总和大于s时,就不需要继续进行。枚举过程采用dfs方法。
总结:
采用dfs方法进行搜索,并在过程中合理的剪枝,顺利解决问题。
代码:
#include <iostream>
#include <vector>
using std::vector;
int count, n, k, s;
int* num;
vector<int> res;
void solve(int sum, int cur)
{
if (res.size() == k && sum == 0)
{
count++;
return;
}
if (cur >= n || res.size() > k || sum < 0)
return;
solve(sum, cur + 1);
res.push_back(num[cur]);
solve(sum - num[cur], cur + 1);
res.pop_back();
}
int main()
{
int m;
scanf("%d", &m);
for (int i = 0; i < m;i++)
{
count = 0;
scanf("%d%d%d", &n, &k, &s);
num = new int[n];
for (int j = 0; j < n; j++)
{
scanf("%d",&num[j]);
}
solve(s, 0);
printf("%d\n", count);
}
delete[] num;
//system("pause");
}
B-区间选点
题意:
数轴上有 n 个闭区间 [a_i, b_i]。取尽量少的点,使得每个区间内都至少有一个点。
思路:
上课学长讲了思路。。。利用结构体存储区间的左右端点。在数轴上,从左到右对n个区间依次进行判断,如果两个区间有重叠部分,则点的个数不用增加,但需要修改区间端点的值。反之,增加点的个数即可。
总结:
典型的贪心问题,先对区间进行排序,之后计数,更改区间范围,即可解决问题。
代码:
#include <iostream>
#include <algorithm>
using std::min;
using std::sort;
struct node
{
int x, y;
} a[1001];
//升序
bool cmp(node a, node b)
{
return a.x < b.x;
}
int main()
{
int n;
while (scanf("%d", &n) == 1)
{
for (int i = 0; i < n; i++)
scanf("%d%d", &a[i].x, &a[i].y);
sort(a, a + n, cmp);
int count = 1;
for (int i = 0; i < n; i++) //计数,更改区间范围
{
if (a[i].y < a[i + 1].x)
count++;
else
a[i + 1].y = min(a[i].y, a[i + 1].y);
}
printf("%d/n", count);
}
//system("pause");
}
C-区间覆盖
题意:
数轴上有 n (1<=n<=25000)个闭区间 [ai, bi],选择尽量少的区间覆盖一条指定线段 [1, t] (1<=t<=1,000,000)。
思路:
上课学长也讲了思路。。。我选择的是从右向左贪心。
- 首先利用结构体数组存储区间左右端点。
- 在贪心过程:首先选择符合要求的右端点,在这些区间中选择最小的左端点,进而得到一个区间,并修改要求中的右端点。值得一提的是,因为这句话的提醒
(1,2)+(3,4)可以覆盖(1,4)。
对于指定线段[1,t],在过程中我们可以选择[3,5],[6,8]这样的并不直接相连的区间。但是我们不能选择[2,x]作为首区间,首区间必须包含1。所以我们需要对左端点进行特判。这是很容易遗漏的点。
总结:
典型的贪心问题。我刚开始做的时候,使用了过多的sort,结果TE了,现在想想根本没必要使用那么多sort,一次sort即可解决问题。
代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
using std::min;
using std::sort;
struct node
{
int x, y;
} a[25001];
//升序
bool cmp(node a, node b)
{
return a.y < b.y;
}
int main()
{
int count = 0;
int n, t, flag = 1;
scanf("%d%d", &n, &t);
for (int i = 0; i < n; i++)
scanf("%d%d", &a[i].x, &a[i].y);
sort(a, a + n, cmp); //右端点升序排列
while (t > 1)
{
int m = n - 1;
int cnt = n;
if (n == 0 || a[n - 1].y < t)
{
flag = 0;
break;
}
while (a[n - 1].y > t - 1 && n != 0)
{
m = (a[n - 1].x < a[m].x) ? n - 1 : m;
n--;
}
t = (a[m].x == 2) ? 2 : a[m].x - 1; //特判左端点
count++;
}
if (flag == 1)
printf("%d", count);
else
printf("-1");
//system("pause");
}
下一篇: 在数据库中如何高效的实现订座功能
推荐阅读
-
《C语言及程序设计初步》_1.11算术运算符与算术表达式_实践10——分离整数和小数部分
-
程序设计思维与实践 Week5 作业 B - TT's Magic Cat
-
程序设计基石与实践系列之类型提升、内存分配,数组转指针、打桩和矢量变换
-
《C语言及程序设计初步》_1.11算术运算符与算术表达式_实践11——如何买玫瑰
-
《C语言及程序设计初步》_1.11算术运算符与算术表达式_实践12——玩数字
-
《C语言及程序设计》实践项目11 算术运算符与算术表达式
-
程序设计思维与实践 CSP-M2 (3/4/数据班)
-
人机智能交互技术(ROS)实践作业模版与说明
-
《C语言及程序设计初步》_1.11算术运算符与算术表达式_实践10——分离整数和小数部分
-
程序设计基石与实践系列之编写高效的C程序与C代码优化