题目大意:给52张牌,要求从左到右判断第i张牌和第i- 3,或是 i- 1 是否存在数字或是花色相同的话(先考虑i- 3),相同就将这张牌移到相同的那张牌的位置,每个位置不一定只有一张牌,但只有最上面的牌可以移动。
解题思路:为了保证只有最上面的牌可以移动用到栈,为了让后面的牌移动到前面没有牌的位置,用到链表。 先判断第i- 3 张牌,相同移动。不同的话换i- 1,相同移动,不同i++。如果判断相同,i就要等于被改变的位置,因为这里的第一张牌被改变了所以要重新判断。直到没有牌可以移动,顺利的判断到最末尾既可以结束了。
#include<stdio.h>
#include<stack>
using namespace std;
const int N = 55;
struct st{
stack <char> v, c;
st *p;
} * head = NULL , * move = NULL;
st* find(int n) { //寻找前n个
st* f = head;
if(n < 0)
return NULL;
for(int i = 0; i < n; i++)
f = f ->p;
return f;
}
int main() {
while(1) {
int i;
char ch[5];
scanf("%s", &ch);
if(ch[0] == '#')
break;
head = new st();
head -> v.push(ch[0]);
head -> c.push(ch[1]);
head -> p = NULL;
move = head;
for (i = 1; i < 52; i++) {
scanf("%s", &ch);
move -> p = new st();
move -> p -> v.push(ch[0]);
move -> p -> c.push(ch[1]);
move -> p -> p = NULL;
move = move -> p;
}
//从第二个开始找
move = head -> p;
i = 1;
while(move != NULL){
char A, B, C, D;
st* L2 = find(i - 3);
st* L1 = find(i - 1);
if(L2 != NULL){
A = move -> v.top();
C = move -> c.top();
B = L2 -> v.top();
D = L2 -> c.top();
if(A == B || C == D) {
move ->v.pop(); //删除第一张牌
move ->c.pop();
L2 ->v.push(A); //移动牌
L2 ->c.push(C);
if(move -> v.empty()) {
L1 -> p = move -> p; //将move从链表中移除
delete move;
}
i = i - 3;
move = L2; //有移动牌就从移动到的位置开始
continue;
}
}
if(L1 != NULL){
A = move -> v.top();
C = move -> c.top();
B = L1 -> v.top();
D = L1 -> c.top();
if(A == B || C == D) {
move ->v.pop();
move ->c.pop();
L1 ->v.push(A);
L1 ->c.push(C);
if(move -> v.empty()) {
L1 -> p = move -> p;
delete move;
}
i = i- 1;
move = L1;
continue;
}
}
i++; //都没有移动的话,判断下一张牌
move = move -> p;
}
int count = 0;
for(move = head; move != NULL ; move = move -> p)
count++;
if(count > 1)
printf("%d piles remaining:", count);
else
printf("%d pile remaining:", count);
for(move = head; move != NULL ; move = move -> p) {
printf(" %d", move -> v.size());
}
printf("\n");
}
return 0;
}