zoukankan      html  css  js  c++  java
  • 51nod 算法马拉松3 A:序列分解

    System Message (命题人)
    基准时间限制:1 秒 空间限制:131072 KB 分值: 40

    小刀和大刀是双胞胎兄弟。今天他们玩一个有意思的游戏。 大刀给小刀准备了一个长度为n的整数序列。小刀试着把这个序列分解成两个长度为n/2的子序列。

    这两个子序列必须满足以下两个条件:

    1.他们不能相互重叠。

    2.他们要完全一样。

    如果小刀可以分解成功,大刀会给小刀一些糖果。

    然而这个问题对于小刀来说太难了。他想请你来帮忙。


    Input
    第一行给出一个T,表示T组数据。(1<=T<=5)
    接下来每一组数据,输入共2行。
    第一行包含一个整数n (2<=n<=40且为偶数)。
    第二行给出n个整数a[0],a[1],a[2],…,a[2*n-1]表示大刀给小刀准备的序列。(-1,000,000,000<=a[i]<=1,000,000,000)
    Output
    如果小刀可以完成游戏,输出"Good job!!" (不包含引号),否则 输出"What a pity!" (不包含引号)。
    Input示例
    2
    4
    1 1 2 2
    6
    1 2 3 4 5 6
    Output示例
    Good job!!
    What a pity!

    我个人认为这个题目有两处表述的不是很清晰,我自己一开始也不理解什么意思。第一处是两个子序列不能互相重叠,这个意思应该就是说给出的序列中的数要么是给第一序列,要么给第二序列,不能既属于第一序列,有属于第二序列的意思。(如果我理解错了,还望多多指正)。

    另外一点就是

    第二行给出n个整数a[0],a[1],a[2],…,a[2*n-1]表示大刀给小刀准备的序列。

    这里,给出n个数,怎么会到2*n-1呢,不知道是什么意思。


    其实A过之后,再回头看。这道题的意思感觉没必要表述的那么复杂,就是将给出的序列分成两个序列(注意是序列,跟顺序是有关的,所以只统计数量是肯定不行的)。要求分成的两个序列完全相等。

    比方说

    1 7 10 1 7 4 5 7 1 10 7 4 5 1
    这样一个14个数的序列是满足要求的,因为它可以分成

    两个1 7 10 7 4 5 1这样的序列。假设我把两个序列设为up[],down[]

    原来的序列可以这样表示1(down) 7(down) 10(down) 1(up) 7(down) 4(down) 5(down) 7(up) 1(down) 10(up) 7(up) 4(up) 5(up) 1(up)。所以每个元素都按顺序地分成了两个序列。

    我自己的思路是深度搜索,一般来说,会将元素置于down中,符合当前要求的,即与当前down中头元素相等的,可以进入up中,再逐渐这么比较,flag=1就退出,说明OK。down中的元素大于一半了也退出,说明此路不通。

    代码:

    #include <iostream>
    #include <vector>
    #include <map>
    #include <algorithm>
    #include <cstring>
    #include <string>
    using namespace std;
    
    int up[50];
    int down[50];
    int list[50];
    
    int num,flag;
    
    bool pend(int up_size,int down_size)
    {
    	if(up_size!=down_size)
    		return false;
    	else
    	        return true;
    }
    
    void cal(int i,int up_size,int down_size,int cur)
    {
    	if(down_size>(num/2)||flag)
    		return;
    	if(i==num+1)
    	{
    		if(pend(up_size,down_size))
    			flag=1;
    	}
    	else
    	{
    		if(i==1)
    		{
    			down[down_size++]=list[1];
    			cal(i+1,0,down_size,cur);
    		}
    		else
    		{
    			if(list[i]==down[cur])
    			{
    				up[up_size++]=list[i];
    				cal(i+1,up_size,down_size,cur+1);
    
    				down[down_size++]=list[i];
    				cal(i+1,up_size-1,down_size,cur);
    
    			}
    			else
    			{
    				down[down_size++]=list[i];
    				cal(i+1,up_size,down_size,cur);
    			}
    		}
    	}
    
    }
    
    int main()
    {
    
    
    	int test;
            scanf("%d",&test);
    	while(test--)
    	{		
    		int i;
    		scanf("%d",&num);
    		flag=0;
    
    		for(i=1;i<=num;i++)
    		{
    			scanf("%d",&list[i]);
    		}
    		cal(1,0,0,0);
    
    		if(flag)
    			cout<<"Good job!!"<<endl;
    		else
    			cout<<"What a pity!"<<endl;
    	}
    
    	return 0;
    }


    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    新东方英语学习方法
    最易遭老板“炒”的15种员工
    如何阅读代码
    Window 消息大全使用详解
    英语学习的六大原则
    单用户多角色权限的MSSQL实现
    .Net中的5种事务总结
    一个.Net程序员关于学习的思考顺带思考人生
    Server 2005中的分区表(一):什么是分区表?为什么要用分区表?如何创建分区表?
    推荐几个win8系统下载比较好的网站
  • 原文地址:https://www.cnblogs.com/lightspeedsmallson/p/4785863.html
Copyright © 2011-2022 走看看