思路:要在n个数中选择K个,并且让和为S,n<=16,所以dfs,记一下当前选到第几个,选了几个,和是啥就ok。
#include<iostream>
#include<cstdio>
using namespace std;
int n,m,k,a[101],t,ans;
void solve(int x,int y,int sum)
{
if(y==k){if(sum==m) ans++;return ;}
if(x==n+1||sum>m) return ;
solve(x+1,y+1,sum+a[x]);
solve(x+1,y,sum);
return ;
}
int main()
{
scanf("%d",&t);
while (t--)
{
ans=0;
scanf("%d%d%d",&n,&k,&m);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
solve(1,0,0);
printf("%d\n",ans);
}
return 0;
}
总结:裸的dfs,稳点写,多造点样例
思路: 贪心,先右端点升序,再左端点降序,贪心的选每个线段的右端点即可,左端点降序是为了处理线段包含的情况。
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int n,m,k,a[101],t,ans;
struct da{int l,r;}s[1001];
int cmp(const da &x,const da &y)
{
return x.r!=y.r?x.r<y.r:x.l>y.l;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&s[i].l,&s[i].r);
}
sort(s+1,s+n+1,cmp);
int x=-1;
for(int i=1;i<=n;i++)
{
if(s[i].l<=x&&x<=s[i].r) continue;
else ans++,x=s[i].r;
}
printf("%d",ans);
return 0;
}
总结:线段相关的题目要记得考虑包含的情况。
思路:贪心,先左端点升序,再右端点降序,也是为了考虑线段包含的情况,一开始先把肯定无解的情况去掉,然后每次选择一个点,然后选出一个包含这个单的集合,求有多少个集合即可。选点的时候我们贪心的选择每个线段的右端点。
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int n,m,k,t,ans;
bool flag=true;
struct da{int l,r;}s[100001];
int cmp(const da &x,const da &y)
{
return x.l!=y.l?x.l<y.l:x.r>y.r;
}
int main()
{
while(scanf("%d%d",&n,&t)!=EOF)
{
ans=1;flag=true;
for(int i=1;i<=n;i++)
{
scanf("%d%d",&s[i].l,&s[i].r);
}
sort(s+1,s+n+1,cmp);
if(s[1].l!=1) flag=false;
bool flag2= false;
for(int i=1;i<=n;i++)
{
if(s[i].r>=t) flag2=true;
}
if(!flag2) flag= false;
int i=1;
int x=s[1].r,y=0;
while(i<n)
{
if(x>=t) break;
int j=i+1;
while((s[j].l<=x||s[j].l==x+1)&&j<=n) y=max(y,s[j].r),j++;
j--;
if(j==i||s[j].r<=x) {flag=false;break;}
else if(y>x) ans++,x=y;
i=j;
}
if(flag) printf("%d\n",ans);
else printf("-1\n");
}
return 0;
}
总结:要多考虑特殊情况,被卡的很难受。。。