HDU Problem w&&Problem x

下面两道题目对比思考

Problem w:

Problem Description
Search is important in the acm algorithm. When you want to solve a problem by using the search method, try to cut is very important.<br>Now give you a number sequence, include n (&lt;=1000) integers, each integer not bigger than 2^31, you want to find the first P subsequences that is not decrease (if total subsequence W is smaller than P, than just give the first W subsequences). The order of subsequences is that: first order the length of the subsequence. Second order the sequence of each integer’s position in the initial sequence. For example initial sequence 1 3 2 the total legal subsequences is 5. According to order is {1}; {3}; {2}; {1,3}; {1,2}. {1,3} is first than {1,2} because the sequence of each integer’s position in the initial sequence are {1,2} and {1,3}. {1,2} is smaller than {1,3}. If you also can not understand , please see the sample carefully. <br>
 

Input
The input contains multiple test cases.<br>Each test case include, first two integers n, P. (1<n<=1000, 1<p<=10000). <br>
 

Output
For each test case output the sequences according to the problem description. And at the end of each case follow a empty line.
 

Sample Input
 
 
3 5
1 3 2
3 6
1 3 2
4 100
1 2 3 2
 

Sample Output
 
 
1
3
2
1 3
1 2

1

3

2

1 3

1 2

1
2
3
1 2
1 3
2 3
2 2
1 2 3
1 2 2

题意:

输入n个数,找到p个指定的子序列(递增),输出即可,但输出需按子序列长度和位置(原序列的位置)排列。

枚举子序列长度,一个个深搜;

仔细思考56行上下那部分的意思

举个例子:1 6 7 8 7;

输出三位长度的时候 1 6 7;有两种,那个地方就是为了出现两种1 6 7

code:

//求的是最大不下降子序列
#include<bits/stdc++.h>
using namespace std;
int n,m;
int num[1005];
int ans,maxn;//总个数
bool flag;
struct node
{
    int x,p;
    //x表示序列中的元素,p表示每个元素在位置
}s[1005];
void print(int len);
void dfs(int len,int place);
int main()
{
    while(scanf("%d %d",&n,&m)!=EOF)
    {
        ans=0;
        memset(s,0,sizeof(s));
        for(int i=0;i<n;++i)
          scanf("%d",&num[i]);
        for(int i=1;i<=n;++i)//逐个搜索最大值
        {
            maxn=i;
            flag=false;//先假设这一个长度的没有,计算中如果找到这一长度的,改变falg
            dfs(0,0);
            if(ans>=m||!flag)
              break;
        }
        printf("\n");
    }
    return 0;
}
void dfs(int len,int place)//长度和地点
{
    int t;//寻找是否有相同元素是用的
    bool temp;//记录是相同的元素
    if(ans>=m)
      return ;
    if(len==maxn)
    {
        print(len);
        return ;
    }
    for(int i=place;i<n;++i)
      if(!len||(len&&s[len-1].x<=num[i]))//判断是否能加上这个数
      //当前没有数或者当前位置的数大于应该序列中的最后一个数
      {
          if(len==0)//特判子序列为0是,否则会数组越界
            t=0;
          else
            t=s[len-1].p+1;
          //下面的步骤是为了将相同的序列过滤掉

          temp=false;
          for(int j=t;j<i;++j)
          //判断找到的这个元素与上一次找的的元素,它们两之间有没有与当前要插入的元素有相同的
          {
              if(num[j]==num[i])
                temp=true;
          }
          if(temp)
            continue;

          s[len].x=num[i];
          s[len].p=i;
          dfs(len+1,i+1);
      }

}
void print(int len)
{
    ++ans;
    flag=true;//表示这有这一长度的序列
    for(int i=0;i<len-1;++i)
      printf("%d ",s[i].x);
    printf("%d\n",s[len-1].x);
}


Problem x:

Problem Description
Search is important in the acm algorithm. When you want to solve a problem by using the search method, try to cut is very important.<br>Now give you a number sequence, include n (&lt;=100) integers, each integer not bigger than 2^31, you want to find the first P subsequences that is not decrease (if total subsequence W is smaller than P, than just give the first W subsequences). The order of subsequences is that: first order the length of the subsequence. Second order the subsequence by lexicographical. For example initial sequence 1 3 2 the total legal subsequences is 5. According to order is {1}; {2}; {3}; {1,2}; {1,3}. If you also can not understand , please see the sample carefully. <br>
 

Input
The input contains multiple test cases.<br>Each test case include, first two integers n, P. (1<n<=100, 1<p<=100000). <br>
 

Output
For each test case output the sequences according to the problem description. And at the end of each case follow a empty line.
 

Sample Input
 
 
3 5
1 3 2
3 6
1 3 2
4 100
1 2 3 2
 

Sample Output
 
 
1
2
3
1 2
1 3
1
2
3
1 2
1 3
1
2
3
1 2
1 3
2 2
2 3
1 2 2
1 2 3

题意:

输入n个数,找到p个指定的子序列(递增),输出即可,但输出需按子序列长度和排列。

与上一题不一样的地方是:这一题是相同长度的按照字典顺序排序输出

所以需要sort一遍排序,然后按照位置排序输出

同样这个也需要重判(将相同的序列,去除,代码65行左右)

code:

#include<bits/stdc++.h>
using namespace std;
struct Point
{
	int num;//原序列中的数字
	int place;//原序列中的位置
}s[1005];
int save[1005];//储存序列
int n,m;
int maxn;
int ans;
//输出
bool print(int len);
//排序,按照字典(即升序)排序
bool cmp(Point a,Point b);
//搜索
bool dfs(int len,int place,int re);
int main()
{
	while(scanf("%d%d",&n,&m)!=EOF)
	{
		ans=0;
		//memset(s,0,sizeof(s));
		//memset(save,0,sizeof(save));
		for(int i=0;i<n;++i)
		{
			scanf("%d",&s[i].num);
			s[i].place=i;//记录位置
		}
		sort(s,s+n,cmp);
		for(int i=1;i<=n;++i)
		{
			maxn=i;//按照个数搜索
			if(dfs(0,0,-1))//剪枝,当所有序列全输出时,结束
			  break;
		}
		printf("\n");
	}
	return 0;
}
bool cmp(Point a,Point b)
{
	return a.num==b.num?a.place<b.place:a.num<b.num;
	//以元素大小为首,位置为辅排序
}
bool print(int len)
{
	for(int i=0;i<len-1;++i)
	  printf("%d ",save[i]);
	printf("%d\n",save[len-1]);
	if(ans>=m)//判断是否输出结束
	  return true;;
	return false;
}
bool dfs(int len,int place,int re)
{
	if(len==maxn)//满足条件时输出
	{
		++ans;
		if(print(len))
		  return true;
		else
		  return false;
	}
	bool temp=false;//记录第一个数,例如:1 5 6 6
	                //重判:1 5 6,第三个与第四的位置都是6 ,目的是为了不出现两个(1 5 6)
	int cnt;//辅助
	for(int i=place;i<n;++i)
	  if(s[i].place>re)
	  {
	      if(!temp)
	      {
	          temp=true;
	          cnt=s[i].num;
	      }
	      else
	      {
	          if(s[i].num==cnt)
	          continue;
	      }
	      cnt=s[i].num;
	      save[len]=s[i].num;//记录序列
	      if(dfs(len+1,i+1,s[i].place))//深搜
	        return true;
	  }
    return false;
}
//完美的代码





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值