A - 选数问题
题意描述
Given n positive numbers, ZJM can select exactly K of them that sums to S. Now ZJM wonders how many ways to get it!
输入描述
The first line, an integer T<=100, indicates the number of test cases. For each case, there are two lines. The first line, three integers indicate n, K and S. The second line, n integers indicate the positive numbers.
输出描述
For each case, an integer indicate the answer in a independent line.
Remember that k<=n<=16 and all numbers can be stored in 32-bit integer》
输入样例
1
10 3 10
1 2 3 4 5 6 7 8 9 10
输出样例
4
思路分析
本题思路为DFS。从起点开始,分别DFS选第i个数与不选第i个数。注意可行性剪枝即可。
代码
#include<iostream>
#include<cstdio>
using namespace std;
int t,n,k,s,ans,arr[16];
void dfs(int sum,int i,int left){
if(sum==s&&left==0) {
ans++;return;
}
//可行性剪枝
if(i==n||sum>s||left==0||left>n-i) return;
dfs(sum+arr[i],i+1,left-1);//选第i个数
dfs(sum,i+1,left);//不选第i个数;
}
int main(){
cin>>t;
for(int i=0;i<t;i++){
ans=0;
cin>>n>>k>>s;
for(int j=0;j<n;j++){
cin>>arr[j];
}
dfs(0,0,k);
cout<<ans<<endl;
}
}
B 区间选点
题意描述
数轴上有 n 个闭区间 [a_i, b_i]。取尽量少的点,使得每个区间内都至少有一个点(不同区间内含的点可以是同一个)
输入描述
第一行1个整数N(N<=100)
第2~N+1行,每行两个整数a,b(a,b<=100)
输出描述
一个整数,代表选点的数目
思路分析
将所有区间按b从小到大排序。依次遍历区间,若当前区间没有点,则选取最后一个点。
代码
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
struct interval{
int a,b;
bool operator<(const interval & p) const{
return b!=p.b? b<p.b:a>p.a;
}
};
int n,ans,now;
vector<interval> v;
int main(){
cin>>n;
for(int i=0;i<n;i++){
int a=0,b=0;
cin>>a>>b;
v.push_back({a,b});
}
sort(v.begin(),v.end());
int now=v[0].b;ans++;
for(int i=0;i<v.size();i++){
if(!(v[i].a<=now&&v[i].b>=now)){
ans++;now=v[i].b;
}
}
cout<<ans<<endl;
}
C 区间覆盖
题意描述
数轴上有 n (1<=n<=25000)个闭区间 [ai, bi],选择尽量少的区间覆盖一条指定线段 [1, t]( 1<=t<=1,000,000)。覆盖整点,即(1,2)+(3,4)可以覆盖(1,4)。不可能办到输出-1。
输入描述
第一行:N和T
第二行至N+1行: 每一行一个闭区间。
输出描述
选择的区间的数目,不可能办到输出-1
思路分析
1、区间数据整理,如果左端点<1则改为1,右端点>1则改为t。
2、按照a从小到大排序,遍历每个区间。
- 如果当前区间的左端点 ≤ \leq ≤目前覆盖的区间的左端点,更新覆盖的右端点。
- 否则,说明需要选择当前区间。如果当前区间的左端点 ≤ \leq ≤已覆盖区间的右端点+1.那么选取该区间,更新已覆盖的右端点。否则,说明无解。
代码
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<vector>
using namespace std;
int n,t,ans;
struct interval{
int a,b;
bool operator<(const interval & p) const{
return a!=p.a?a<p.a:b>p.b;
}
};
vector<interval> v;
int main(){
int a=0,b=0;
while(scanf("%d%d",&n,&t)!=EOF){
v.clear();
ans=1;
for(int i=0;i<n;i++){
scanf("%d%d",&a,&b);
if(a<1) a=1;
if(b>t) b=t;
v.push_back({a,b});
}
sort(v.begin(),v.end());
int start=1,now=0,end=v[0].b;
if(v[0].a!=1){
cout<<"-1"<<endl;
continue;
}
for(int i=0;i<n;i++){
if(v[i].a<=start){
end=max(end,v[i].b);
}
else{
ans++;
start=end+1;
if(v[i].a<=start){
end=v[i].b;
}else{
ans=-1;break;
}
}
if(end==t){
break;
}
}
if(end==t){
cout<<ans<<endl;
}
else{cout<<"-1"<<endl;
}
}
}