NOIP 2008 双栈排序 解体报告

  也不知是怎么,以前没看懂为什么要用二分图,现在就懂了,以后也许碰到类似的题目还会想到用二分图,因为当i<j<k,且num[i] < num[j] && num[i] > num[k]的时候,肯定是不能将i和j放在同一个栈了(是放在同一个栈,不是同时在一个栈里面。)

  嗯,上代码把:

#include <stdio.h>
#include <stdlib.h>
int num[1000];
int min[1000];
int map[1000000], next[1000000];
int end, head[1000];

void add(int a, int b)
{
	map[end] = b;
	next[end] = head[a];
	head[a] = end++;
}

int group[1000];

void srch(int i, int k)
{
	int j, t;
	group[i] = k;
	for(j = head[i]; j != -1; j = next[j]){
		t = map[j];
		if(group[t] == 0){
			srch(t, 3 - k);
		}else if(group[t] != 3 - k){
			printf("0\n");
			exit(0);
		}
	}
}

int stack[2][1000];
int top[2];
int output[2000];
int last;

void push(int k, int id)
{
	stack[id][top[id]++] = k;
}

int gettop(int id)
{
	if(top[id] == 0){
		return 0xFFFFFFF;
	}
	return stack[id][top[id] - 1];
}

int pop(int id)
{
	return stack[id][--top[id]];
}

int main(int argc, char **argv)
{
	int i, j;
	int n;
	scanf("%d", &n);
	for(i = 0; i < n; i++){
		head[i] = -1;
		scanf("%d", &num[i]);
	}
	min[n - 1] = num[n - 1];
	for(i = n - 2; i >= 0; i--){
		if(min[i + 1] > num[i]){
			min[i] = num[i];
		}else{
			min[i] = min[i + 1];
		}
	}
	for(i = 0; i < n - 2; i++){
		for(j = i + 1; j < n - 1; j++){
			if(num[i] < num[j] && num[i] > min[j + 1]){
				add(i, j);
				add(j, i);
			}
		}
	}
	for(i = 0; i < n; i++){
		if(group[i] == 0){
			srch(i, 1);
		}
	}
	i = 1;
	j = 0;
	while(i <= n){
		while(group[j] == 1 && num[j] < gettop(0)){
			output[last++] = 'a';
			push(num[j], 0);
			j++;
		}
		while(gettop(0) == i){
			output[last++] = 'b';
			pop(0);
			i++;
		}
		while(group[j] == 2 && num[j] < gettop(1)){
			output[last++] = 'c';
			push(num[j], 1);
			j++;
		}
		while(gettop(1) == i){
			output[last++] = 'd';
			pop(1);
			i++;
		}
	}
	for(i = 0; i < last; i++){
		if(i != 0){
			printf(" ");
		}
		printf("%c", output[i]);
	}
	printf("\n");
	return 0;
}

  

转载于:https://www.cnblogs.com/yylogo/archive/2011/08/11/NOIP-2008-3.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值