• 洛谷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("
    ");//每次换行
    	}
    	return 0;
    }
    
  • 相关阅读:
    NYOJ458
    NYOJ67
    NYOJ105
    NYOJ1071
    NYOJ463
    C语言练字用小软件 — Practise_Calligraphy_1.0(ANSI)
    NYOJ276
    NYOJ455
    NYOJ74
    Jzoj4458 密钥破解——Pollard-rho
  • 原文地址:https://www.cnblogs.com/ShineEternal/p/10834286.html
Copyright © 2020-2023  润新知