洛谷P1155 双栈排序
这题什么毒瘤......之前看一直没思路,然后心说写个暴搜看能有多少分,然后就A了??!
题意:给你一个n排列,求它们能不能通过双栈来完成排序。如果能输出最小字典序方案。
[update]这里面加了一个错误的剪枝。这是个假算法。
解:首先我们发现有一个策略,就是可以出栈的时候出栈,否则就在两个栈中选栈顶大于它且栈顶尽量小的那个入栈。如果这样还GG就无解。
但是这样不能保证字典序最小。因为入栈栈顶较小的可以保证决策包容性,但是可能你入另一个栈不会引起冲突。
于是想到搜索,T飞。
加上剪枝:如果先入的栈顶较小,那么不用入另一个栈。AC。
然后发现过不了hack数据:
5 2 4 1 3 5
这组数据在最后要先入栈5,再出栈4。
稍微调整一下搜索顺序就行了。AC。
1 #include <cstdio> 2 #include <algorithm> 3 4 const int N = 10010, INF = 0x3f3f3f3f; 5 6 int a[N], b[N], c[N], d[N], ta, tb, tc, td, p[N << 2], tp, n; 7 8 void DFS(int k) { 9 /* 10 printf("k = %d tb = %d tc = %d td = %d \n", k, tb, tc, td); 11 printf("b: "); 12 for(int i = 1; i <= tb; i++) { 13 printf("%d ", b[i]); 14 } 15 printf("\nc: "); 16 for(int i = 1; i <= tc; i++) { 17 printf("%d ", c[i]); 18 } 19 printf("\ned: "); 20 printf("%d \n", td); */ 21 22 if(td == n) { 23 // 24 for(int i = 1; i <= tp; i++) { 25 putchar(p[i] + 'a' - 1); 26 if(i < tp) { 27 putchar(' '); 28 } 29 } 30 exit(0); 31 return; 32 } 33 if(a[k] == d[td] + 1) { 34 d[++td] = a[k]; 35 p[++tp] = 1; 36 p[++tp] = 2; 37 DFS(k + 1); 38 td--; 39 tp--; 40 tp--; 41 return; 42 } 43 44 if(a[k] < b[tb] && k <= n) { 45 b[++tb] = a[k]; 46 p[++tp] = 1; 47 DFS(k + 1); 48 tp--; 49 tb--; 50 if(b[tb] < c[tc]) { 51 return; 52 } 53 } 54 55 if(b[tb] == d[td] + 1) { 56 d[++td] = b[tb]; 57 tb--; 58 p[++tp] = 2; 59 DFS(k); 60 tp--; 61 b[++tb] = d[td]; 62 td--; 63 return; 64 } 65 66 if(a[k] < c[tc] && k <= n) { 67 c[++tc] = a[k]; 68 p[++tp] = 3; 69 DFS(k + 1); 70 tp--; 71 tc--; 72 return; 73 } 74 if(c[tc] == d[td] + 1) { 75 d[++td] = c[tc]; 76 tc--; 77 p[++tp] = 4; 78 DFS(k); 79 tp--; 80 c[++tc] = d[td]; 81 td--; 82 return; 83 } 84 85 return; 86 } 87 88 int main() { 89 scanf("%d", &n); 90 for(int i = 1; i <= n; i++) { 91 scanf("%d", &a[i]); 92 } 93 94 b[0] = INF; 95 c[0] = INF + 1; 96 97 DFS(1); 98 99 printf("0"); 100 return 0; 101 } 102 /** 103 10 104 10 2 8 1 7 9 3 4 5 6 105 106 a a c a b b c a a b a b a b a b d d b b 107 108 */