思路:要在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;
}
總結:要多考慮特殊情況,被卡的很難受。。。