CSU 1973:给自己出题的小X(DFS或DP)
2017-07-29 20:38
267 查看
给自己出题的小X
Time limit: 1 Sec Memory limit:128 MbProblem Description
小X学习了dfs,为了练习搜索,开始给自己出题玩。玩着玩着,一会把自己难住了,一会又被自己难倒了,真是有趣诶!
小X出的题:
现在有N个不同的正整数,求它们可以组成多少个这样的集合,满足:
集合内的元素数量S>1
集合内任意两个数的差的绝对值都大于集合内的元素数量。
Input
第一行,一个正整数T(T<=20)表示数据组数。对于每组数据,有两行。第一行为一个正整数N(3≤N≤25),第二行为N个用空格隔开的正整数xi(xi≤200)。
Output
对于每组数据,输出一行一个整数表示题中所描述的集合的个数。Sample Input
15
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 D(1973): 给自己出题的小X
- (CSU - 1973)给自己出题的小X
- CSUOJ 1973 给自己出题的小X DFS
- CSU1973: 给自己出题的小X
- CodeForces 149D Coloring Brackets(区间DP+dfs)
- CSU - 1600:Twenty-four point(DFS)
- 记忆化搜索POJ-1088(dfs+dp)
- hihocoder1104(Dfs预处理+树形DP)
- 278 First Bad Version 【拓展分析,自己出题】
- POJ 2192 Zipper (DFS / DP)
- HDU 1501 Zipper(DP,DFS)
- 1272 摘果子(树形dp,dfs)
- 【dp+dfs】VK Cup 2012 Round 1-D. Distance in Tree
- HDU 1241 DFS入门。。做了一个晚上,自己总算入门了。
- HDU1561 树形DFS+DP
- Codeforces 467D. Fedor and Essay (Graphs,dfs,dp,hashing,strings,图论综合型好题)
- dp专辑F - Mondriaan's Dream [dp+dfs]
- CodeForces - 937D Sleepy Game [dfs+DP]
- 滑雪(百练1088) (dp+dfs)
- hdu 1078 FatMouse and Cheese【dfs+dp】