洛谷P2790 ccj与zrz之积木问题 题解

题目链接:https://www.luogu.org/problemnew/show/P2790

这题码量稍有点大。。。

分析:

这道题模拟即可。因为考虑到所有的操作vector可最快捷的实现,所以数组动态vector。每一种情况分别考虑。

其他的见代码注释

部分过长的注释防在这里,请对照序号到代码中查看。

:wa意为a的位置,记录当前a所在位置的序号。
wb意为b的位置,记录当前b所在位置的序号。
ca意为a的层数,记录当前a所在这堆积木中第几个。
cb意为b的层数,记录当前b所在这堆积木中第几个。

其他定义显而易见。

:search遍历一遍所有位置所有积木,找到a或b后记录他们的位置和位置中第几个,相当于为后面的一个初始化吧。

:此函数即move onto,按照题意模拟即可,之后④⑤⑥均如此,具体模拟步骤会详细说明。

代码:

#include<cstdio>
#include<vector>
#include<cstring>
using namespace std;
int wa,wb,ca,cb;//①
char s1[10],s2[10];
int a,b;
vector<int>v[30];
int n;
void search()//②
{
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<v[i].size();j++)
		{
			if(v[i][j]==a)
			{
				wa=i;
				ca=j;
			}
			if(v[i][j]==b)
			{
				wb=i;
				cb=j;
			}
		}
	}
}
void moon()//③
{
	for(int i=ca+1;i<v[wa].size();i++)
	{
		v[v[wa][i]].push_back(v[wa][i]);
	}//把a以上的归位
	for(int i=cb+1;i<v[wb].size();i++)
	{
		v[v[wb][i]].push_back(v[wb][i]);
	}//把b以上的归位
	v[wa].resize(ca);//只保留当前vector到a-1
	v[wb].resize(cb+1);//但是b要保留,因为a是要摞到b上的
	v[wb].push_back(a);//摞上去
}//下面的都换汤不换药,我想大家都应该知道
void moov()//④
{
	for(int i=ca+1;i<v[wa].size();i++)
	{
		v[v[wa][i]].push_back(v[wa][i]);
	}
	v[wa].resize(ca);
	v[wb].push_back(a);
}
void pion()//⑤
{
	for(int i=cb+1;i<v[wb].size();i++)
	{
		v[v[wb][i]].push_back(v[wb][i]);
	}
	v[wb].resize(cb+1);
	for(int i=ca;i<v[wa].size();i++)
	{
		v[wb].push_back(v[wa][i]);
	}
	v[wa].resize(ca);
}
void piov()//⑥
{
	for(int i=ca;i<v[wa].size();i++)
	{
		v[wb].push_back(v[wa][i]);
	}
	v[wa].resize(ca);
}
int main()
{
	scanf("%d",&n);
	for(int i=0;i<n;i++)
	{
		v[i].push_back(i);
	}
	while(1)
	{
		scanf("%s",s1);
		if(strcmp(s1,"quit")==0)break;//提前判断是否退出
		scanf("%d%s%d",&a,s2,&b);
		search();
		if(wa==wb)continue;//根据题意,如果a和b在同一堆,那么忽略
		if(strcmp(s1,"move")==0&&strcmp(s2,"onto")==0)moon();
		if(strcmp(s1,"move")==0&&strcmp(s2,"over")==0)moov();
		if(strcmp(s1,"pile")==0&&strcmp(s2,"onto")==0)pion();
		if(strcmp(s1,"pile")==0&&strcmp(s2,"over")==0)piov();
		//逐一判断每种操作,其中相应的子函数对应去两个单词的首字母连起来
	}
	for(int i=0;i<n;i++)
	{
		printf("%d:",i);//暂时不输出括号,有了再打
		for(int j=0;j<v[i].size();j++)
		{
			printf(" %d",v[i][j]);//当前位置有积木,那么就打出来,别忘了空格
		}
		printf("\n");//每次换行
	}
	return 0;
}
posted @ 2018-11-26 20:14  vercont  阅读(236)  评论(0编辑  收藏  举报