http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=18191
题意: 下面的步骤看别人的,
機器手臂有以下幾種合法搬積木的方式(a和b是積木的編號):
move a onto b
move a over b
pile a onto b
pile a over b
quit
前四個動作中若a=b,或者a, b在同一堆積木中,那麼這樣的動作算是不合法的。所有不合法的動作應該被忽略,也就是對各積木均無改變
思路:就是一个模拟栈的问题,对自己还是有一点难度,折腾了几天,最后在poj找到测试数据,才摆脱re的折磨。基础差,各种差!!!
pile[i][i]表示第i堆第i个数,in[i]表示第i堆的总数,q[i]表示第i张牌的当前位置,模拟就好了,注意细节。
奉上一组poj上的测试数据:
9
move 4 onto 1
move 8 onto 3
move 7 onto 8
move 8 onto 1
move 2 onto 6
move 1 over 6
move 3 onto 7
move 8 onto 3
pile 2 onto 3
move 4 onto 5
move 6 onto 4
pile 3 onto 4
quit
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <cstring>
#include <string>
#include <algorithm>
#include <string>
#include <set>
#include <functional>
#include <numeric>
#include <sstream>
#include <stack>
#include <map>
#include <queue>
#define CL(arr, val) memset(arr, val, sizeof(arr))
#define ll long long
#define inf 0x7f7f7f7f
#define lc l,m,rt<<1
#define rc m + 1,r,rt<<1|1
#define pi acos(-1.0)
#define L(x) (x) << 1
#define R(x) (x) << 1 | 1
#define MID(l, r) (l + r) >> 1
#define Min(x, y) (x) < (y) ? (x) : (y)
#define Max(x, y) (x) < (y) ? (y) : (x)
#define E(x) (1 << (x))
#define iabs(x) (x) < 0 ? -(x) : (x)
#define OUT(x) printf("%I64d\n", x)
#define lowbit(x) (x)&(-x)
#define Read() freopen("a.txt", "r", stdin)
#define Write() freopen("dout.txt", "w", stdout);
#define N 100005
using namespace std;
const int len = 100;
int pile[len][len],in[len],q[len]; //pile[i][i]表示第i堆牌第i张,in表示第i堆牌总数,q表示第i张牌的当前位置
int pd(int x,int y) //判断x跟y在不在同一堆
{
if(q[x]==q[y]) return 1; //判断当前位置 是不是在同一堆即可
return 0;
}
void solve(int x) //将 x上的积木放回原来的位置 不包括x
{
int i,ans,y,z; //从x这一堆 从上往下找
ans=in[q[x]]; //当前堆 积木总数
y=q[x]; //当前堆编号
for(i=ans;pile[y][i]!=x;i--)
{
z=pile[y][i]; //当前堆需要移动的积木编号
q[z]=z; //当前积木移到初始位置,那么 当前积木移动后当前位置变为自身编号
pile[z][++in[z]]=z; //重新存储
in[y]--; //当前堆减1
}
}
void solve2(int x,int y) //将 x本身和其上的积木一起放到y上,并且按顺序放
{
int i,ans=0,z,y1,y2;
for(i=in[q[x]];pile[q[x]][i]!=x;i--)
{
ans++; //求出x在当前堆的位置
}
z=in[q[x]]; //当前堆 总数
y1=q[x];//当前堆 编号
for(i=z-ans;i<=z;i++) //移动
{
q[pile[y1][i]]=q[y]; //把积木的当前位置改掉
pile[q[y]][++in[q[y]]]=pile[y1][i]; //移动
in[y1]--; //总数减 1
}
}
int main()
{
//Read(); //文件读取
int n,i,j;
char s[30],a[10],b[10];
int c,d;
while(scanf("%d",&n)!=EOF) //读入n,代表有n张牌
{
getchar();
CL(pile,0); //清空数组
CL(q,0);
CL(in,0);
for(i=0;i<n;i++) //初始化
{
in[i]=1;
q[i]=i;
pile[i][1]=i;
}
while(1)
{
gets(s);
if(s[0]=='q') break;
sscanf(s,"%s %d %s %d",a,&c,b,&d);
if(c==d||pd(c,d)) continue;
if(strcmp(a,"move")==0)
{
if(strcmp(b,"onto")==0)
{
if(in[q[c]]>1)solve(c);
if(in[q[d]]>1)solve(d);
pile[q[d]][++in[q[d]]]=pile[q[c]][in[q[c]]--];
q[c]=q[d];
}
else if(strcmp(b,"over")==0)
{
if(in[q[c]]>1) solve(c);
pile[q[d]][++in[q[d]]]=pile[q[c]][in[q[c]]--];
q[c]=q[d];
}
}
else if(strcmp(a,"pile")==0)
{
if(strcmp(b,"onto")==0)
{
if(in[q[d]]>1)solve(d);
solve2(c,d);
}
else if(strcmp(b,"over")==0)
{
solve2(c,d);
}
}
}
for(i=0;i<n;i++)
{
if(in[i]==0)
{
printf("%d:\n",i);
}
else
{
printf("%d:",i);
for(j=1;j<=in[i];j++)
{
if(j!=in[i]) printf(" %d",pile[i][j]);
else printf(" %d\n",pile[i][j]);
}
}
}
}
return 0;
}
下面是别人用vector写的,比我的规范多了!
#include <cstdio>
#include <vector>
#include <stack>
using namespace std;
const int MAXN = 30;
vector<int> pile[MAXN];
int pos[MAXN];
const int MOVE = 0;
const int PILE = 1;
const int ONTO = 0;
const int OVER = 1;
void init(int n){
for(int i=0; i<n; i++){
pile[i].clear();
pile[i].push_back(i);
pos[i] = i;
}
}
bool ReadInstruct(int &insA, int &insB, int &x, int &y)
{
char s1[10];
scanf("%s", s1);
if(s1[0] == 'q') return false;
if(s1[0] == 'm') insA = MOVE;
else insA = PILE;
scanf("%d", &x);
scanf("%s", s1);
if(s1[1] == 'n') insB = ONTO;
else insB = OVER;
scanf("%d", &y);
return true;
}
void PrintPile(int n)
{
for(int i=0; i<n; i++){
printf("%d:", i);
for(int j=0; j<pile[i].size(); j++){
printf(" %d", pile[i][j]);
}
printf("\n");
}
}
void ReturnAbove(int x){
int px = pos[x];
while(1){
int y = pile[px].back();
if(y == x) break;
pile[px].pop_back();
pile[y].push_back(y);
pos[y] = y;
}
}
void StoreAbove(stack<int> &stk, int x){
int px = pos[x];
while(1){
int y = pile[px].back();
pile[px].pop_back();
stk.push(y);
if(y == x) break;
}
}
void MoveTo(stack<int>& stk, int y) //move stk to y
{
int py = pos[y];
while(!stk.empty()){
int x = stk.top(); stk.pop();
pos[x] = py;
pile[py].push_back(x);
}
}
int main(){
//freopen("in", "r", stdin);
int n;
scanf("%d", &n);
init(n);
int insA, insB, a, b;
while(1){
if(ReadInstruct(insA, insB, a, b) == false)
break;
if(pos[a] == pos[b]) continue;
if(insA == MOVE) //move
ReturnAbove(a);
if(insB == ONTO) //onto
ReturnAbove(b);
stack<int> stk;
StoreAbove(stk, a);
MoveTo(stk, b);
}
PrintPile(n);
}