Description: Much to Mr. Book’s amazement, his entire algorithm class has completed the homework that he assigned only the day before. The students have dumped their homework, one page per student, unceremoniously in a pile on his desk.
There are N students in the class, and each of them have a unique integer student ID from 1 to N. Mr. Book wants the homework to be sorted by student ID with the page from student #1 at the top,all the way down to the page to student #N at the bottom. Mr. Book is a lazy fellow. He doesn’t want to put much effort into sorting the pile himself.
To sort the homework, Mr. Book comes up with an idea which could be described as follows:Every time he moves a page, he’ll only move it from the original pile to his finished stack, which initially starts empty. Furthermore, he’ll only move the top or bottom page of the remaining pile, and he’ll only place it on the top or bottom of his destination stack. Is it possible for Mr. Book to sort the homework with such a method?
Input: Input begins with a line which contains an integer T , i.e. the number of test cases. For each case, there are two lines. The first contains the integer N , i.e. the number of students. The second contains a permutation of the integers from 1 to N . These are the students’ IDs in the order their homework appears in the pile, from bottom to top.
Output: For the i-th case, print a line containing “Case #i: ” followed by “yes” if Mr. Book can sort the homework by student ID, or “no” if he can’t.
Sample Input:
5
4
1 2 3 4
4
1 3 2 4
9
2 4 3 1 5 9 6 7 8
6
4 3 2 1 6 5
5
3 4 5 1 2
Sample Output:
Case #1: yes
Case #2: no
Case #3: no
Case #4: yes
Case #5: yes
其实就是一个首尾进出栈的问题。对于一个序列,如 3 4 5 1 2.每次从首 或者 尾拿出一个元素,插入栈,看其是否可以 在允许 栈顶和栈底插入的情况下,形成 1 2 3 4 5的序列,可以输出yes,否则输出no.
那么 栈结构可以是这样的,3 -> 3 4-> 3 4 5->2 3 4 5->1 2 3 4 5,yes
再如序列:1 3 2 4. 如果入栈 1,然而后面只能入栈 3或者4,就不能连续。如果入栈 4,然而后面只能入栈1或者2.不能连续。故输出no.
我们可以考虑2种情况
A:第一个入栈元素为序列左边
B:第一个入栈元素为序列右边
对于A,我们接下来 入栈剩余序列的左边或者右边,必须保证 入栈元素 和 栈顶或者栈底 的元素连续,如果不连续,则 A情况失败,如果 序列全部入栈,那么最小值为1,最大值为序列元素个数。
对于B,我们是同样的分析。
/*
1.运行环境:windows 7 + 32位系统 + vs2013
2.无差错控制,无安全检查,无特殊处理。
3.带刺的银杏 2015.05.18 于 苏州 (中雨)
*/
#include
int flag_left = 0; // 成功则修改为1
int judge_left(int a[],int len,int min,int max,int low,int high) //a为序列,len是序列长度,min,max为当前栈中元素 最小值和最大值,low,high为待入栈的序列 的首尾指针。
{
if(min == 1 && max == len) //成功
{
flag_left = 1 ;
return 1;
}
if ( a[low] == min-1 ) //相当于入栈序列的左边
return judge_left(a,len,a[low],max,low+1,high);
else if(a[low] == max + 1 )
return judge_left(a,len,min,a[low],low+1,high);
else if(a[high] == min - 1) //相当于入栈序列的右边
return judge_left(a,len,a[high],max,low,high-1);
else if (a[high] == max + 1)
return judge_left(a,len,min,a[high],low,high-1);
else
return -1; //两边都不能保证连续,故此次入栈失败,即 退出
}
int main()
{
int num,i,len,result1=0,result2=0,cases=0;
int a[100];
scanf("%d",&num); //测试案例的个数
while(cases++ < num) //接受每个案例的输入
{
flag_left = -1;
result1 = 0; //记录A情况的结果
result2 = 0; //记录B情况的结果
scanf("%d",&len);
for(i=0;i<len;i++)
scanf("%d",&a[i]);
judge_left(a,len,a[0],a[0],1,len-1);
result1 = flag_left;
flag_left = 0;
judge_left(a,len,a[len-1],a[len-1],1,len-1);
result2 = flag_left;
printf("Case #%d:%s\n",cases,(result1 ==1 || result2 == 1)?"yes":"no");
}
}
递归真是一种好办法,代码量如此少。同时,判断结束的条件 if(min == 1 && max == len) 也是蛮有意思的。值得一试。