csu D(1973): 给自己出题的小X

题目:

D(1973): 给自己出题的小X

            Time Limit: 1 Sec       Memory Limit: 128 Mb       Submitted: 38       Solved: 9    

Description

小X学习了dfs,为了练习搜索,开始给自己出题玩。
玩着玩着,一会把自己难住了,一会又被自己难倒了,真是有趣诶!
小X出的题:
现在有N个不同的正整数,求它们可以组成多少个这样的集合,满足:

  • 集合内的元素数量S>1
  • 集合内任意两个数的差的绝对值都大于集合内的元素数量。

Input

第一行,一个正整数T(T<=20)表示数据组数。

对于每组数据,有两行。第一行为一个正整数N(3≤N≤25),第二行为N个用空格隔开的正整数xi(xi≤200)。

Output

对于每组数据,输出一行一个整数表示题中所描述的集合的个数。

Sample Input

1
5
2 3 5 8 1

Sample Output

6

Hint

{5,8},{1,5},{1,8},{2,5},{2,8},{3,8}.

解题思路(复制粘贴版):
可以从第2开始枚举集合里的元素数目,在确定了元素数目之后dfs依次搜索第i个数,dfs过程中保证第i个数合法。
另外,不枚举集合内元素数目也是可以的,直接dfs依次枚举第i个数,当确定下一个数是否合法时,需要检查截止目前的最小相邻间隔是否大于目前集合内的元素数量。这一过程最好在dfs时记录并传递一个相邻间隔最小值。

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
using namespace std;
typedef long long ll;
const double PI = acos(-1.0);
const double eps = 1e-6;
const int INF = 100000;
const int maxn = 33;

int a[maxn];
int T,n,m;
ll ans;

void dfs(int num,int pos,int pre,int min_dif)
{
    if(num>1&&min_dif>num)
    {
        ans++;
        //printf("num:%d pos:%d pre:%d ans:%d\n",num,pos,pre,ans);
    }
    if(pos==n)
        return;
    for(int i=pos;i<n;i++)
    {
        if(a[i]-pre>num+1)
        {
            dfs(num+1,i+1,a[i],min(min_dif,a[i]-pre));
        }
    }
}

int main()
{
    scanf("%d",&T);
	while(T--)
    {
        scanf("%d",&n);
        for(int i=0;i<n;i++)
        {
            scanf("%d",&a[i]);
        }
        ans=0;
        sort(a,a+n);
        dfs(0,0,-INF,INF);
        printf("%lld\n",ans);
    }
    return 0;
}

/**********************************************************************
	Problem: 1973
	User: 201601090128
	Language: C++
	Result: AC
	Time:296 ms
	Memory:2020 kb
**********************************************************************/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值