1 条题解
-
0
解题思路
问题分析:
游戏的目标是将所有牌按非递减顺序放入目标堆。
牌只能从库存堆移动到中间堆,或从中间堆移动到目标堆。
目标堆的牌必须是非递减的,因此每次从中间堆移动到目标堆的牌必须大于或等于目标堆的当前最上面的牌(初始时目标堆为空,可以接受任何牌)。
关键观察:
中间堆的行为类似于栈,只能从栈顶操作。
目标堆的牌必须按非递减顺序排列,因此需要确保中间堆的牌能够按顺序移动到目标堆。
需要模拟牌的移动过程,尝试所有可能的合法移动,直到所有牌都移动到目标堆或无法继续移动。
解题方法:
使用深度优先搜索(DFS)或广度优先搜索(BFS)来模拟所有可能的移动序列。
需要维护库存堆、两个中间堆和目标堆的状态。
每次可以选择:
将库存堆的顶牌移动到中间堆或中间堆(如果库存堆不为空)。
将中间堆或中间堆的顶牌移动到目标堆(如果该牌大于或等于目标堆的顶牌)。
为了避免重复状态和无限循环,可以记录已经访问过的状态。
优化:
由于牌的数量可能较多(最多张),直接搜索可能会很慢,因此需要剪枝或使用启发式方法。
可以优先尝试将中间堆的牌移动到目标堆(“pop”操作),因为这是直接向目标前进的步骤。
C++代码实现:
//用图论的思想来做题 //二分图着色 #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> using namespace std; #define maxn 250 struct { int v,next; }edge[maxn*maxn]; int n; int stock[maxn], f[maxn]; int head[maxn], ecount, color[maxn], q[maxn]; int out[maxn]; bool ok; int stk1[maxn], stk2[maxn]; int top1, top2, step; inline int min(int a,int b){ return a<b?a:b; } void input() { for (int i =0; i < n; i++) { scanf("%d", &stock[i]); out[i] = stock[i]; } } void addedge(int&a, int&b) { edge[ecount].next = head[a]; edge[ecount].v = b; head[a] = ecount++; } void bfs(int&s) { int front =0; int rear =1; q[0] = s; color[s] =1; while (front != rear) { int a = q[front++]; for (int i = head[a]; i !=-1; i = edge[i].next) { int b = edge[i].v; if (!color[b]) { q[rear++] = b; color[b] =3- color[a]; } else if (color[a] == color[b]) { ok =false; return; } } } } void make(int i) { int a = stock[i]; bool did =true; while (did) { did =false; if (top1 >0&& stk1[top1 -1] ==out[step]) { top1--; printf("pop 1\n"); step++; did =true; } if (top2 >0&& stk2[top2 -1] ==out[step]) { top2--; printf("pop 2\n"); step++; did =true; } } if (i <0) return; if (color[i] ==1) { stk1[top1++] = a; printf("push 1\n"); } else { stk2[top2++] = a; printf("push 2\n"); } } void print() { top1 = top2 =0; step =0; for (int i = n -1; i >=0; i--) make(i); make(-1); } void work() { memset(head, -1, sizeof(head)); f[0] = stock[0]; int i; for (i =1; i < n; i++) f[i] = min(f[i -1], stock[i]); ecount =0; for (i =1; i < n -1; i++) { for (int j = i +1; j < n; j++) { if (stock[j] >= stock[i]) continue; if (stock[j] > f[i -1]) { addedge(i, j); addedge(j, i); } } } ok =true; memset(color, 0, sizeof(color)); for (i =0; i < n; i++) { if (!color[i]) bfs(i); if (!ok) { printf("impossible\n"); return; } } print(); } int main() { //freopen("t.txt", "r", stdin); int t =0; while (scanf("%d", &n), n) { t++; printf("#%d\n", t); input(); sort(out, out+ n); work(); } return 0; }
- 1
信息
- ID
- 1091
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者