1 条题解

  • 0
    @ 2025-8-24 21:47:44

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar daifucong
    王展鹏天下第一

    搬运于2025-08-24 21:47:44,当前版本为作者最后更新于2018-10-14 19:27:19,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    这是一道简单的模拟题。

    据说可以将三维平面上的投影转化到二维平面上的问题做。

    然而我太弱了,只会分类讨论。

    我们发现只要处理每个小立方体的顶面,前面,右面的颜色就可以了。废话

    cnt[i][j]cnt[i][j]表示输入数据从上到下第ii行,从左到右第jj列的立方体个数。

    对于顶面的颜色,我们对每束光线分类讨论:

    1. 对于方向竖直向下的光线,我们直接把光线加上去即可。
    2. 对于从左射来的光线,如果存在一个h>0h>0,使得cnt[x][yh]cnt[x][y]hcnt[x][y-h]-cnt[x][y]\geqslant h,则这束光线不能照到位于(x,y)(x,y)的最上面的小立方体的顶面的任何一部分。其它类似的光线同理。
    3. 对于从右下方向射来的光线:

    如果存在一个h>0h>0,使得cnt[x+h][y+h]cnt[x][y]hcnt[x+h][y+h]-cnt[x][y]\geqslant h,则这束光线不能照到位于(x,y)(x,y)的最上面的小立方体的顶面的任何一部分。

    如果存在一个h>0h>0,使得cnt[x+h][y+h1]cnt[x][y]hcnt[x+h][y+h-1]-cnt[x][y]\geqslant h,则这束光线不能照到位于(x,y)(x,y)的最上面的小立方体的顶面的左边部分和下边部分。

    如果存在一个h>0h>0,使得cnt[x+h1][y+h]cnt[x][y]hcnt[x+h-1][y+h]-cnt[x][y]\geqslant h,则这束光线不能照到位于(x,y)(x,y)的最上面的小立方体的顶面的右边部分和上边部分。

    其它类似的光线同理。

    对于右面的颜色,我们还是对每束光线分类讨论,但是只要讨论33束光线:

    令这个小立方体的高度为HeightHeight

    1. 对于从正右方向射来的光线,如果存在一个h>0h>0,使得cnt[x][y+h]Heighthcnt[x][y+h]-Height\geqslant h,则这束光线不能找到这个立方体的右边。

    2. 对于从右下方向射来的光线:

    如果存在一个h>0h>0,使得cnt[x+h1][y+h]Heighth1cnt[x+h-1][y+h]-Height\geqslant h-1,则这个小立方体的整个右面不能被这束光照到。

    如果存在一个h>0h>0,使得cnt[x+h][y+h]Heighthcnt[x+h][y+h]-Height\geqslant h,则这个小立方体的整个右面不能被这束光照到。

    如果存在一个h0h\geqslant 0,使得cnt[x+h+1][y+h+1]Heighthcnt[x+h+1][y+h+1]-Height\geqslant h,则这个小立方体右面的左边部分和下边部分不能被这束光照到。

    1. 对于从右上方向射来的光线,处理方法和从右下方向射来的光线类似。

    对于前面的颜色,处理方法和右面的颜色类似。

    至于输出的话其实就是这道题P1058

    上代码:

    #include<bits/stdc++.h>
    using namespace std;
    char base[20][20]={"",
    "\0    +-------+",
    "\0   /4\\1111\'/|",
    "\0  /44.*\'22/1|",
    "\0 /.3333\\2/1/|",
    "\0+-------+1.2|",
    "\0|\\11111/|\\:2|",
    "\0|4\\111/2|4*2|",
    "\0|44\\1/22|4:\\|",
    "\0|444X222|4\'3+",
    "\0|44/3\\22|/3/ ",
    "\0|4/333\\2|3/  ",
    "\0|/33333\\|/   ",
    "\0+-------+    "};
    const int baseh=13;
    char ans[5001][5001];int cnt[101][101];int n,m;int ansh,answ;
    char getcube[20][20];
    inline void setit(int startx,int starty){for(int i=13,x=startx;i>=1;i--,x--) for(int j=1,y=starty;j<=13;j++,y++) if(getcube[i][j]!=' ') ans[x][y]=getcube[i][j];}
    struct Col
    {
    	bool R,B,G;Col(){R=B=G=0;}Col(char c){R=B=G=0;if(c=='R')R=1;if(c=='B') B=1;if(c=='G')G=1;}
    	inline char getcol()
    	{
    		if(R==0&&B==0&&G==0) return 'K';if(R==0&&B==0&&G==1) return 'G';
    		if(R==0&&B==1&&G==0) return 'B';if(R==0&&B==1&&G==1) return 'C';
    		if(R==1&&B==0&&G==0) return 'R';if(R==1&&B==0&&G==1) return 'Y';
    		if(R==1&&B==1&&G==0) return 'P';if(R==1&&B==1&&G==1) return 'W';
    		assert(0);return '\0';
    	}
    };
    inline Col operator +(const Col &a,const Col &b){Col res;res.R=a.R||b.R;res.B=a.B||b.B;res.G=a.G||b.G;return res;}
    inline void Add(Col &a,char c){a=a+Col(c);}
    //个人认为这样定义可以方便处理颜色重叠的问题
    char light[4][4];
    struct Block
    {
    	Col Ul,Ur,Uf,Ub;
    	Col Fu,Fd,Fl,Fr;
    	Col Ru,Rd,Rf,Rb;
    	inline void Getcube()
    	{
    		for(int i=1;i<=baseh;i++) for(int j=1;j<=baseh;j++)
    		{
    			getcube[i][j]=base[i][j];
    			if(i>=6&&j<=9)
    			{
    				if(base[i][j]=='1') getcube[i][j]=Fu.getcol();
    				if(base[i][j]=='2') getcube[i][j]=Fr.getcol();
    				if(base[i][j]=='3') getcube[i][j]=Fd.getcol();
    				if(base[i][j]=='4') getcube[i][j]=Fl.getcol();
    			}
    			if(i>=5&&j>9)
    			{
    				if(base[i][j]=='1') getcube[i][j]=Ru.getcol();
    				if(base[i][j]=='2') getcube[i][j]=Rb.getcol();
    				if(base[i][j]=='3') getcube[i][j]=Rd.getcol();
    				if(base[i][j]=='4') getcube[i][j]=Rf.getcol();
    			}
    			if(i<5)
    			{
    				if(base[i][j]=='1') getcube[i][j]=Ub.getcol();
    				if(base[i][j]=='2') getcube[i][j]=Ur.getcol();
    				if(base[i][j]=='3') getcube[i][j]=Uf.getcol();
    				if(base[i][j]=='4') getcube[i][j]=Ul.getcol();
    			}
    		}
    		getcube[3][12]=Ru.getcol();
    		getcube[4][11]=Ru.getcol();
    	}//将这个立方体的实际输出放到getcube[][]字符数组中
    }a[101][101][101];
    inline void SolveUpColor()
    {
    	for(int i=1;i<=n;i++) for(int j=1;j<=m;j++)
    	{
    		int high=cnt[i][j];
    		a[i][j][high].Ub=a[i][j][high].Uf=a[i][j][high].Ul=a[i][j][high].Ur=Col(light[2][2]);
    		//light from up
    		bool flag1=1,flag2=1;//flag1:left front,flag2:right back
    		int curx=i-1,cury=j-1,curcnt=1;
    		while(curx&&cury&&flag1){if(cnt[curx][cury]-cnt[i][j]>=curcnt) flag1=flag2=0;curx--;cury--;curcnt++;}
    		curx=i;cury=j-1;curcnt=1;
    		while(flag1&&curx&&cury){if(cnt[curx][cury]-cnt[i][j]>=curcnt) flag1=0;curx--;cury--;curcnt++;}
    		curx=i-1;cury=j;curcnt=1;
    		while(flag2&&curx&&cury){if(cnt[curx][cury]-cnt[i][j]>=curcnt) flag2=0;curx--;cury--;curcnt++;}
    		if(flag1) Add(a[i][j][high].Ul,light[1][1]),Add(a[i][j][high].Uf,light[1][1]);
    		if(flag2) Add(a[i][j][high].Ub,light[1][1]),Add(a[i][j][high].Ur,light[1][1]);
    		//light from left back
    		flag1=1;curx=i-1;cury=j;curcnt=1;
    		while(flag1&&curx){if(cnt[curx][cury]-cnt[i][j]>=curcnt) flag1=0;curx--;curcnt++;}
    		if(flag1)
    		{
    			Add(a[i][j][high].Ul,light[1][2]),Add(a[i][j][high].Uf,light[1][2]);
    			Add(a[i][j][high].Ub,light[1][2]),Add(a[i][j][high].Ur,light[1][2]);
    		}
    		//light from back
    		flag1=flag2=1;curx=i-1,cury=j+1;curcnt=1;//flag1:left back,flag2:right front
    		while(flag1&&curx&&cury<=m){if(cnt[curx][cury]-cnt[i][j]>=curcnt) flag1=flag2=0;curx--;cury++;curcnt++;}
    		curx=i-1,cury=j;curcnt=1;
    		while(flag1&&curx&&cury<=m){if(cnt[curx][cury]-cnt[i][j]>=curcnt) flag1=0;curx--;cury++;curcnt++;}
    		curx=i;cury=j+1;curcnt=1;
    		while(flag2&&curx&&cury<=m){if(cnt[curx][cury]-cnt[i][j]>=curcnt) flag2=0;curx--;cury++;curcnt++;}
    		if(flag1) Add(a[i][j][high].Ul,light[1][3]),Add(a[i][j][high].Ub,light[1][3]);
    		if(flag2) Add(a[i][j][high].Uf,light[1][3]),Add(a[i][j][high].Ur,light[1][3]);
    		//light from right back
    		flag1=1;curx=i;cury=j-1;curcnt=1;
    		while(flag1&&cury){if(cnt[curx][cury]-cnt[i][j]>=curcnt) flag1=0;cury--;curcnt++;}
    		if(flag1)
    		{
    			Add(a[i][j][high].Ul,light[2][1]),Add(a[i][j][high].Uf,light[2][1]);
    			Add(a[i][j][high].Ub,light[2][1]),Add(a[i][j][high].Ur,light[2][1]);
    		}
    		//light from left
    		flag1=1;curx=i;cury=j+1;curcnt=1;
    		while(flag1&&cury<=m){if(cnt[curx][cury]-cnt[i][j]>=curcnt) flag1=0;cury++;curcnt++;}
    		if(flag1)
    		{
    			Add(a[i][j][high].Ul,light[2][3]),Add(a[i][j][high].Uf,light[2][3]);
    			Add(a[i][j][high].Ub,light[2][3]),Add(a[i][j][high].Ur,light[2][3]);
    		}
    		//light from right
    		flag1=flag2=1;curx=i+1;cury=j-1;curcnt=1;//flag1:left back,flag2:right front
    		while(flag1&&curx<=n&&cury){if(cnt[curx][cury]-cnt[i][j]>=curcnt) flag1=flag2=0;curx++;cury--;curcnt++;}
    		curx=i;cury=j-1;curcnt=1;
    		while(flag1&&curx<=n&&cury){if(cnt[curx][cury]-cnt[i][j]>=curcnt) flag1=0;curx++;cury--;curcnt++;}
    		curx=i+1;cury=j;curcnt=1;
    		while(flag2&&curx<=n&&cury){if(cnt[curx][cury]-cnt[i][j]>=curcnt) flag2=0;curx++;cury--;curcnt++;}
    		if(flag1) Add(a[i][j][high].Ul,light[3][1]),Add(a[i][j][high].Ub,light[3][1]);
    		if(flag2) Add(a[i][j][high].Uf,light[3][1]),Add(a[i][j][high].Ur,light[3][1]);
    		//light from left front
    		flag1=1;curx=i+1;cury=j;curcnt=1;
    		while(flag1&&curx<=n){if(cnt[curx][cury]-cnt[i][j]>=curcnt) flag1=0;curx++;curcnt++;}
    		if(flag1)
    		{
    			Add(a[i][j][high].Ul,light[3][2]),Add(a[i][j][high].Uf,light[3][2]);
    			Add(a[i][j][high].Ub,light[3][2]),Add(a[i][j][high].Ur,light[3][2]);
    		}
    		//light from front
    		flag1=flag2=1;curx=i+1;cury=j+1;curcnt=1;//flag1:left front,flag2:right back
    		while(flag1&&curx<=n&&cury<=m){if(cnt[curx][cury]-cnt[i][j]>=curcnt) flag1=flag2=0;curx++;cury++;curcnt++;}
    		curx=i+1;cury=j;curcnt=1;
    		while(flag1&&curx<=n&&cury<=m){if(cnt[curx][cury]-cnt[i][j]>=curcnt) flag1=0;curx++;cury++;curcnt++;}
    		curx=i;cury=j+1;curcnt=1;
    		while(flag2&&curx<=n&&cury<=m){if(cnt[curx][cury]-cnt[i][j]>=curcnt) flag2=0;curx++;cury++;curcnt++;}
    		if(flag1) Add(a[i][j][high].Ul,light[3][3]),Add(a[i][j][high].Uf,light[3][3]);
    		if(flag2) Add(a[i][j][high].Ur,light[3][3]),Add(a[i][j][high].Ub,light[3][3]);
    		//light from right front
    	}
    }//处理顶面的颜色
    inline void SolveRightColor()
    {
    	for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) for(int high=1;high<=cnt[i][j];high++)
    	{
    		if(j<m&&cnt[i][j+1]>=cnt[i][j]) continue;
    		int flag1,flag2;int curx,cury,curhigh;
    		flag1=1;curx=i;cury=j+1;curhigh=high;
    		while(flag1&&cury<=m){if(cnt[curx][cury]>=curhigh) flag1=0;cury++;curhigh++;}
    		if(flag1)
    		{
    			Add(a[i][j][high].Rb,light[2][3]);Add(a[i][j][high].Rd,light[2][3]);
    			Add(a[i][j][high].Rf,light[2][3]);Add(a[i][j][high].Ru,light[2][3]);
    		}
    		//light from right
    		flag1=flag2=1;curx=i+1;cury=j+2;curhigh=high+1;//flag1:up back,flag2:front down
    		while(flag1&&curx<=n&&cury<=m){if(cnt[curx][cury]>=curhigh) flag1=flag2=0;curx++;cury++;curhigh++;}
    		curx=i+1;cury=j+1;curhigh=high+1;
    		while(flag1&&curx<=n&&cury<=m){if(cnt[curx][cury]>=curhigh) flag1=flag2=0;curx++;cury++;curhigh++;}
    		curx=i+1;cury=j+1;curhigh=high;
    		while(flag2&&curx<=n&&cury<=m){if(cnt[curx][cury]>=curhigh) flag2=0;curx++;cury++;curhigh++;}
    		if(flag1) Add(a[i][j][high].Ru,light[3][3]),Add(a[i][j][high].Rb,light[3][3]);
    		if(flag2) Add(a[i][j][high].Rf,light[3][3]),Add(a[i][j][high].Rd,light[3][3]);
    		//light from right front
    		flag1=flag2=1;curx=i-1;cury=j+2;curhigh=high+1;//flag1:up front,flag2:down back
    		while(flag1&&curx&&cury<=m){if(cnt[curx][cury]>=curhigh) flag1=flag2=0;curx--;cury++;curhigh++;}
    		curx=i-1;cury=j+1;curhigh=high+1;
    		while(flag1&&curx&&cury<=m){if(cnt[curx][cury]>=curhigh) flag1=flag2=0;curx--;cury++;curhigh++;}
    		curx=i-1;cury=j+1;curhigh=high;
    		while(flag2&&curx&&cury<=m){if(cnt[curx][cury]>=curhigh) flag2=0;curx--;cury++;curhigh++;}
    		if(flag1) Add(a[i][j][high].Ru,light[1][3]),Add(a[i][j][high].Rf,light[1][3]);
    		if(flag2) Add(a[i][j][high].Rd,light[1][3]),Add(a[i][j][high].Rb,light[1][3]);
    		//light from right back
    	}
    }//处理右面的颜色
    inline void SolveFrontColor(){
    	for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) for(int high=1;high<=cnt[i][j];high++)
    	{
    		if(i<n&&cnt[i+1][j]>=cnt[i][j]) continue;
    		int flag1,flag2,curx,cury,curhigh;
    		flag1=1;curx=i+2;cury=j;curhigh=high+1;
    		while(flag1&&curx<=n){if(cnt[curx][cury]>=curhigh) flag1=0;curx++;curhigh++;}
    		if(flag1)
    		{
    			Add(a[i][j][high].Fd,light[3][2]);Add(a[i][j][high].Fl,light[3][2]);
    			Add(a[i][j][high].Fr,light[3][2]);Add(a[i][j][high].Fu,light[3][2]);
    		}
    		//light from front
    		flag1=flag2=1;curx=i+1;cury=j+1;curhigh=high+1;//flag1:left up,flag2:right down
    		while(flag1&&curx<=n&&cury<=m){if(cnt[curx][cury]>=curhigh) flag1=flag2=0;curx++;cury++;curhigh++;}
    		curx=i+2;cury=j+1;curhigh=high+1;
    		while(flag1&&curx<=n&&cury<=m){if(cnt[curx][cury]>=curhigh) flag1=flag2=0;curx++;cury++;curhigh++;}
    		curx=i+1;cury=j+1;curhigh=high;
    		while(flag2&&curx<=n&&cury<=m){if(cnt[curx][cury]>=curhigh) flag2=0;curx++;cury++;curhigh++;}
    		if(flag1) Add(a[i][j][high].Fl,light[3][3]),Add(a[i][j][high].Fu,light[3][3]);
    		if(flag2) Add(a[i][j][high].Fr,light[3][3]),Add(a[i][j][high].Fd,light[3][3]);
    		//light from right front
    		flag1=flag2=1;curx=i+1;cury=j-1;curhigh=high+1;//flag1:right up,flag2:left down
    		while(flag1&&curx<=n&&cury){if(cnt[curx][cury]>=curhigh) flag1=flag2=0;curx++;cury--;curhigh++;}
    		curx=i+2;cury=j-1;curhigh=high+1;
    		while(flag1&&curx<=n&&cury){if(cnt[curx][cury]>=curhigh) flag1=flag2=0;curx++;cury--;curhigh++;}
    		curx=i+1;cury=j-1;curhigh=high;
    		while(flag2&&curx<=n&&cury){if(cnt[curx][cury]>=curhigh) flag2=0;curx++;cury--;curhigh++;}
    		if(flag1) Add(a[i][j][high].Fr,light[3][1]),Add(a[i][j][high].Fu,light[3][1]);
    		if(flag2) Add(a[i][j][high].Fl,light[3][1]),Add(a[i][j][high].Fd,light[3][1]);
    		//light from left front
    	}
    }//处理前面的颜色
    inline void print()
    {
    	ansh=0;answ=1+m*8+n*4;
    	for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) ansh=max(ansh,1+4*(n-i+1)+8*cnt[i][j]);
    	for(int i=1;i<=ansh;i++) for(int j=1;j<=answ;j++) ans[i][j]=' ';
    	for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) for(int k=1;k<=cnt[i][j];k++)
    	{
    		int getx=ansh-4*(n-i)-8*(k-1),gety=1+(j-1)*8+(n-i)*4;
    		a[i][j][k].Getcube();
    		setit(getx,gety);
    	}
    	for(int i=1;i<=ansh;i++)
    	{
    		for(int j=1;j<=answ;j++) putchar(ans[i][j]);
    		putchar('\n');
    	}
    }//输出不解释了
    inline void init()
    {
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&cnt[i][j]);
    	for(int i=1;i<=3;i++) for(int j=1;j<=3;j++) cin>>light[i][j];
    }
    int main()
    {
    	init();
    	SolveUpColor();
    	SolveRightColor();
    	SolveFrontColor();
    	print();
    	return 0;
    }
    

    本题在省选当中出现,还是比较可做的,毕竟省选有55个小时。

    反正ZJOI考场上遇到这题我就头铁刚

    • 1

    信息

    ID
    2399
    时间
    1000ms
    内存
    125MiB
    难度
    6
    标签
    递交数
    0
    已通过
    0
    上传者