hdu 2610 (dfs)

点击打开链接


题意:

给你n个数组成一个序列,要求找出m个子序列,要求这m个子序列非递减。

输出的时候先按长度,再按每个数字的位置。。。。

转:

/*

分析:
(1)题意很简单就是在给定的序列中找到固定个数的递增的子序列,如果子序列的总个数少于要求的个数,那么就把所有的子序列输出即可,注意每组测试用例就为有一空行。
(2)技巧一:重判,这里有两个重判,第一个重判是判断如果搜索的是子序列的第一个元素,那么判断从原始序列开始到当前位置是否已经出现过该元素,若出现过则之前肯定搜索过该元素,则放弃该元素的搜索。第二个重判,当搜索的不是子序列的第一个元素时,则判断子序列的前一个元素对应原始序列的位置,然后从该位置下一个元素开始到到当前搜索的位置之前判断该元素是否出现过,如果出现过,说明该子串出现过重复的,则放弃该元素。这里的两个重判需要好好地想想,很巧妙。
(3)技巧二:剪枝,这里的一个剪枝技巧是做了一个标记位,假如我在搜索长度为3的子串时,发现没有一个符合的,那么就不可能存在长度为4的子串符合条件。如果没有这个剪枝就会超时,看来影响很大的。。。。。

*/

转自:点击打开链接


#include"stdio.h"
#include"string.h"
#define N 1001

int a[N];
int n,m;
struct node 
{
	int n,pos;
}A[N];
int f;
int cnt;
int len;
//上个深度找到的数的位置为s
//这个深度找到的数的位置为e
//看s+1到e-1之间是否有与位置e上的数相等的数
//如果有的话,说明e位置的数之前已经用过了,再用的话肯定重复。。。。
int fun(int s,int e)
{
	int i;
	for(i=s+1;i<e;i++)
		if(a[i]==a[e])return 0;
	return 1;
}

void print(int len)
{
	int i;
	for(i=0;i<len-1;i++)
		printf("%d ",A[i].n);
	printf("%d\n",A[i].n);
}
//depΪÉî¶È,posΪËÑË÷µÄλÖÃ
void dfs(int dep,int pos)
{
	if(cnt>=m)return ;
	if(dep==len)
	{
		f=1;
		cnt++;
		print(len);
		return ;
	}
	for(int i=pos;i<n;i++)
	{
		if(dep==0||(dep!=0&&A[dep-1].n<=a[i]))
		{
			if(dep==0&&!fun(-1,i))continue;
			if(dep!=0&&!fun(A[dep-1].pos,i))continue;
			A[dep].n=a[i];
			A[dep].pos=i;
			dfs(dep+1,i+1);
		}
	}
	return ;
}

int main()
{
	int i;
	while(scanf("%d%d",&n,&m)!=-1)
	{
		for(i=0;i<n;i++)
			scanf("%d",&a[i]);
		cnt=0;
		for(i=1;i<n;i++)
		{
			f=0;
			len=i;
			dfs(0,0);
			if(cnt>=m||f==0)break;
		}
		printf("\n");
	}
	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值