A——选数问题
题意
有N个正整数,在其中选出K个数使其和为S,求出有多少种取法。
输入:
1
10 3 10
1 2 3 4 5 6 7 8 9 10
123
输出
4
1
思路:
dfs搜索,记录每一层和总值,递归实现,如果超过就舍弃,进行减枝。
#include <iostream>
#include <cstring>
using namespace std;
int n,k,s,ans=0;
int a[100000]={0};
void check(int f,int m,int sum ) //f-floorc层数 m-mark 数组标记
{
if(f== k &&sum==s)
{
ans++;
return ;
}
else if(f>k || sum>s)
return;
for(int i=m ;i<n; i++)
{
check(f+1,i+1,sum+a[i]);
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
ans=0;
memset(a,0,sizeof(a));
scanf("%d %d %d",&n,&k,&s);
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
check(0,0,0);
cout<<ans<<endl;
}
return 0;
}
B——区间选点
题意
有n个闭区间,选取尽量少的点,使每个区间内都含有点。
测试样例:
输入:
2
1 5
4 6
123
输出:
1
1
分析:
我们可以用 pair记录每一个区间,用sort重写cmp排序,我们可以发现,只要从大到小,如果下一个区间包含上一个 的尾巴,就可以用尽量少的点
代码
#include <cstdio>
#include <algorithm>
using namespace std;
bool cmp(pair<int,int > x, pair<int,int > y) {
if(x.second == y.second)
return x.first > y.first;
return x.second < y.second;
}
int main() {
int n, temp, ans = 1; // temp表示当前选择的点的位置,我们从第二个点开始,因此初始化计数器为1
scanf("%d", &n);
pair<int,int > a[n];
for(int i = 0; i < n; i++)
scanf("%d %d", &a[i].first, &a[i].second);
//
sort(a, a+n, cmp); //按右边排序
temp = a[0].second;
for(int i = 1; i < n; i++)
if(a[i].first > temp) {
temp = a[i].second;
ans++;
}
printf("%d\n", ans);
return 0;
}
C——区间覆盖
题意
有n个区间,选择尽量少的区间覆盖[1, t]。
注:[1,2], [3,4]能覆盖[1,4]
测试样例:
输入:
3 10
1 7
3 6
6 10
1234
输出:
2
1
与上一个题类似
但是情况更多;我们得多加一个判断,按首端和长度排序后,一个先驱pair去选择手段不大于前一个末端加1的线段,直至选到最优的,由此往复,直到最后判断先驱是否符合要求
贪心算法
代码:
#include <cstdio>
#include <algorithm>
using namespace std;
bool cmp(pair<int,int > x, pair<int,int > y) {
if(x.first == y.first)
return x.second < y.second;
return x.first < y.first;
}
int main() {
int n,t, temp, ans = 0; // temp表示当前选择的点的位置,我们从第二个点开始,因此初始化计数器为1
scanf("%d %d", &n,&t);
pair<int,int > a[n];
for(int i = 0; i < n; i++)
scanf("%d %d", &a[i].first, &a[i].second);
//
sort(a, a+n, cmp);
// for(int i = 0; i < n; i++)
// printf("-- %d %d\n", a[i].first, a[i].second);
// if(a[0].first>1 || a[n-1].second<t){
// printf("-1");
// return 0;
// }
//
temp = 0;
pair<int,int > now(0,0) ;
int sub = a[0].second-a[0].first;
int mark=0;
for(int i = 0; i < n; i++){
if(a[i].first <= temp+1&&a[i].second>temp&&a[i].second>now.second) {
mark=1;
now=a[i];
// printf("//---- %d %d\n", now.first, now.second);
}
if( mark==1 && a[i].first > temp+1 ){
temp = now.second;
mark=0;
ans++;
// printf("---- %d %d\n", now.first, now.second);
if(temp>=t) break;
if(a[i].first <= temp+1&&a[i].second>temp&&a[i].second>now.second) {
mark=1;
now=a[i];
// printf("//---- %d %d\n", now.first, now.second);
}
}
if(mark==0&&a[i].first > temp+1){
printf("-1");
return 0;
}
if(i==n-1&&mark==1){
if(now.second>=t){
ans++;
// printf("---- %d %d\n", now.first, now.second);
break;
}
else
{
printf("-1");
return 0;
}
}
}
printf("%d\n", ans);
return 0;
}