CSU 1973:给自己出题的小X(DFS或DP)
来源:互联网 发布:苹果版解压缩软件 编辑:程序博客网 时间:2024/06/10 19:52
给自己出题的小X
Problem 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
题意:
给出N(N≤25)个不同的正整数,求有多少个这样的集合,集合内存在至少两个元素,且任意两个元素差值都大于集合内的元素数量。
解题思路:
以下是出题人的题解
正如题面中所描述的,出题人的意图是出一个搜索题。
该题,是按一定顺序枚举子集,然后检查子集是否合法。
时间上,子集数目最多为2N2N 个,判断是否合法可以在搜索过程中检查,因此时间复杂度为O(T*2N2N),T为数据组数。
不过根据题目数据范围xi≤200,合理地搜索一定可以剪枝,因此实际上搜索用时会低于极限复杂度,时间上可以接受。
具体来说:第一步还是先排个序,这样,“任意两个元素差值都大于集合内的元素数量”就等价于“排序后间隔最小的两个相邻元素差值大于集合内的元素数量”;
然后,可以从2开始枚举集合里的元素数目,在确定了元素数目之后dfs依次搜索第i个数,dfs过程中保证第i个数合法。
另外,不枚举集合内元素数目也是可以的,直接dfs依次枚举第i个数,当确定下一个数是否合法时,需要检查截止目前的最小相邻间隔是否大于目前集合内的元素数量。这一过程最好在dfs时记录并传递一个相邻间隔最小值。
值得一提的是,此题可以不用搜索完成,使用动态规划————事实上,在许多时候,指数级复杂度的搜索问题都可以尝试着用动态规划来解决。
其中一种动态规划方法是,定义dp[i][j][k] 表示前i个数里选j个数,并且第i个数要选,相邻最小间隔大于k的方案数。
初始化为dp[i][1][k]=1(1 ≤ i ≤ N, 1 ≤ k ≤ N)
状态转移方程是:
dp[i][j][k]=∑p=1idp[p][j−1][k](a[i]−a[p]>k)
答案为∑Ni=1∑Nk=2dp[i][k][k]
时间复杂度为O(N^4 )。
我的解法:DFS。先排序。用last记录上一个加入集合的下标,i记录当前准备用来加入集合的下标,s表示当前集合中元素数量,m表示当前集合中差的绝对值的最小值。如果当前元素可以加入,ans++,继续更新last,i,s和m后继续搜下一层。不管当前元素能不能加入,都要考虑不加入的情况,只有i+1,其他不变继续搜下一层。DP的方法有空再写写吧
Code:
#include <iostream>#include <algorithm>#include <cstdio>using namespace std;const int INF=1e8;int a[30];int ans=0;int n;void DFS(int last,int i,int s,int m){ if(i>=n||s<=0||m<=s) return; if(a[i]-a[last]>s+1&&m>s+1) { ans++; DFS(i,i+1,s+1,min(m,a[i]-a[last])); } DFS(last,i+1,s,m);}int main(){ int T; scanf("%d",&T); while(T--) { scanf("%d",&n); for(int i=0;i<n;i++) scanf("%d",a+i); sort(a,a+n); ans=0; for(int i=0;i<n-1;i++) { DFS(i,i+1,1,INF); } printf("%d\n",ans); } return 0;}/********************************************************************** Problem: 1973 User: HN0017 Language: C++ Result: AC Time:112 ms Memory:2020 kb**********************************************************************/
- CSU 1973:给自己出题的小X(DFS或DP)
- csu D(1973): 给自己出题的小X
- COJ1973-给自己出题的小X
- CSU1973: 给自己出题的小X
- CSU 1513 Kick the ball! ( 概率DP & DFS )
- CSU 1719(智障选手的DFS)
- [CSU 1802 小X的战斗力] 拓扑排序+Floyd
- CSU 1919:不醉不归(神奇的dp)
- HDU1584(dfs回溯 或 区间dp)
- 【2010集训队出题】小Z的袜子
- CSU 1979: 古怪的行列式(DFS八皇后变形)
- 小杂程序(给自己看的)
- 给自己的小建议(持续更新)
- POJ 3034 (dp) 锤子尼玛能在棋盘外面。。出题不带这么坑的
- POJ 1775 dfs或dp
- Divideing Jewels【dfs或DP】
- bzoj 1616 dfs 或 dp
- csu 1964(状压DP)
- 静态顺序表的实现
- Redis基本操作
- 开发板测试网口带宽方法
- hdu4565(矩阵快速幂)
- Children’s Queue HDU
- CSU 1973:给自己出题的小X(DFS或DP)
- Spark 键值对RDD操作
- C语言——实例009 输出国际象棋棋盘。
- 函数(2)
- git 总结
- 分布式存储-fastdfs+glusterfs- 学习笔记
- Android 6.0动态权限申请
- hdu 4990 Reading comprehension(矩阵乘法)
- 美国国家安全局如何分析通话数据