A - 选数问题
题目描述
有n个数,求从中选择和为S的K个数的方案有多少个。
解题过程
可以找出所有选择K个数的所有方案,然后从里面找出和为S的。
找出所有方案,对于该数组而言就是对应位置的数有没有被选择,可以用一个长度为n的二进制数来表示选择的情况,对应位置为1即被选中,0则是没有。
#include <iostream>
#include <cmath>
using namespace std;
int countt(int i) {
int cot = 0;
while( i>0 ) {
if(i & 1){
++cot;//被选择
}
i =i>> 1;//判断下一位
}
return cot;
}//计算选了多少数
int main(int argc, char** argv) {
int t;
cin>>t;
for(int yy=0;yy<t;yy++)
{int n,cc,sum;
cin>>n;
cin>>cc;
cin>>sum;
int num[n+1];
int b[n+1]={0};
int k=0,v;
int cot[2];
cot[0]=0;
for(int j=0;j<n;j++)
{
cin>>v;
num[k]=v;
k++;
}
int count=0;
for (int i = 0; i < pow(2, n); i++)
{
if (countt(i) == cc) //是否选了cc个数
{
int u=i,ss=0;
for (int j = 0; j < n; j++)
{
if (u & 1 ) //该位被选。
{
ss = ss+num[j];
}
u=u>>1;//下一位
}
if (ss == sum)
count++;//符合
}
}
cout<<count<<endl;
}
return 0;
}
B - 区间选点
解题过程
虽然通过上课的内容知道这一次的题应该是用贪心策略,但一开始还是不知道怎么写,甚至试图用区间长度排序……
因为要取最少的点所以点应该尽量分布在多个区间的交界中并且为了在更多区间内它应该在最右侧,也就是说只要下一个区间没有出前面区间的交界处那么点就不需要增加。变成了判断区间有没有出界的问题了…。只要区间的左端点小于交界区的右端点就没有出界。
为了找交界要给区间排序,右端点小的排在前面。则左端点小于等于前一区间右端点时与前一区间有交界,当左端点大于前一区间右端点时说明出了该交界需要的点增加。
#include <iostream>
#include <cstdio>
#include <algorithm>
struct rl
{
int right;
int left;
int lenth;
};
bool cmp(rl a, rl b) {
if(a.right != b.right)
return a.right < b.right;
else
return a.left > b.left;
}
using namespace std;
int main(int argc, char** argv) {
int n,count=0;
cin>>n;
rl num[n];int pre;
for(int i=0;i<n;i++)
{cin>>num[i].left;
cin>>num[i].right;
}
sort(num, num+n, cmp);
pre=num[0].right;
for(int i = 1; i < n; i++)
if(num[i].left > pre)
{ count++;
pre=num[i].right;
}
cout<<count+1<<endl;
return 0;
}
C - 区间覆盖
解题过程
这道题一度让我非常痛苦,换了无数种方法都无法AC,先是怀疑排序,然后怀疑数据处理,最后怀疑人生。后来得到了大佬的怜悯,才知道原来覆盖【1,t】必须从1开始……原本还以为会有负数觉得有小于等于1的就可以。堪忧的语文能力甚至影响了做题。
选择尽量少的区间就意味着同样条件下选更长的,将区间排序,左端点小的排在前,相同时右端点大的在前(更大的区间)。如果最小的左端点不是1那么无法覆盖。
记录现在的区间的右端点和前一个区间的右端点,从第一个区间开始,如果发现左端点在上一区间内且右端点更大的区间,则将该区间标记为当前区间(如果右端点为t则可以覆盖,区间数+1结束循环输出答案),如果发现该区间超过了上一区间的范围,将当前区间变为上一区间,区间数+1,如果超过了当前区间则说明不可能做到跳出循环(一开始没有写这个判断居然也过了就是慢了点,没有意义地循环完了所有区间……)。
#include <iostream>
#include<algorithm>
using namespace std;
struct rl
{
int left;
int right;
} ;
bool cmp(rl s1,rl s2)
{
if(s1.left>s2.left)
return 0;
if(s1.left==s2.left)
{
if(s1.right<s2.right)
return 0;
}
return 1;
}
int main()
{ int n,t,l,r,sta=1,end=1;
int count=1;
scanf("%d%d",&n,&t);
rl num[25002];
for(int i=0;i<n;i++)
{
scanf("%d%d",&l,&r);
num[i].left=l;
num[i].right=r;
}
sort(num,num+n,cmp);
if(num[0].left!=1)
{
cout<<"-1";
}
else{
int pre=num[0].right,now=num[0].right;
for(int i=1;i<n;++i)
{
if(num[i].left>now+1)
{
break;
}
if(num[i].left>pre+1)
{
pre=now;
count++;
}
if(num[i].left<=pre+1)
{
if(num[i].right>now)
now=num[i].right;
if(num[i].right==t)
{
pre=t;
count++;
break;
}
}
}
if(pre==t)
cout<<count;
else
cout<<"-1"<<endl;
}
return 0;
}