立體圖【題目連接】ios
而後由於有點(不是有點,很是)懵,所以我只能看一步寫一步。數組
首先整體思路:ide
將三維立體圖看作二維平面圖,先肯定出二維圖的長和寬,而後,按照三維立體圖的透視順序,從最後一排的最左開始依次覆蓋操做,直到覆蓋完成,不用的地方填‘.’;spa
首先是處理二維圖的長和寬:3d
(首先要說的是,如下全部長均指豎向,寬均爲橫向)code
通過畫圖找規律咱們瞭解到了對於一個方塊,若是咱們在它上面增長一個方塊,對於這個方塊和新增的方塊的某個對應點來講,長增長了3,寬增長0;:blog
對應點用不一樣顏色標出;字符串
而後對於先後擺放的狀況:get
從圖中能夠看出,長增長了2,寬增長了2;string
而後對於左右擺放的狀況:
由圖中能夠看出,長莫得增長,寬增長了4;
而後對應如下數組:
//寬的增長量 int dm[4]={0,0,4,2};//1豎着摞,2橫着摞,3先後摞 //長的增長量 int dn[4]={0,3,0,2};//1豎着摞,2橫着摞,3先後摞
而後咱們求一下咱們要存的二維平面的大小:
對於橫放的寬:從最左下角開始計算,先計算
中,最右下的位置(圖中紅圈內紫色點的位置);
=(m-1)*dm[2]+5(首先第一個方塊佔了5個單位,而後剩餘的m-1個方塊,每放一個,增長4個單位)
計算完成後,再計算
中剩餘位置也就是紅圈‘+’所在位置,如何計算剩下的長度呢,咱們須要用到先後擺放的增長量:仍是一樣,首先先把第一個方塊單列,這個方塊的(右面吧)爲寬提供了3的價值(可是要注意的是,由於第一個方塊最左下的貢獻與上面的計算重複了,因此實際咱們只須要+2),剩餘n-1個方塊,每一個爲寬提供了2個價值。
所以寬mm=5+(m-1)*dm[2]+(n-1)*dm[3]+2;
再來看長,由於lz看的題解的博主:小蒟蒻皮皮魚(友情安利,這是個大佬)他本身說他比較菜,用的枚舉的方法,lz也只看懂了枚舉的方法:
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) nn=max(nn,atlas[i][j]*dn[1]+dn[3]*(n-i+1)+1); //枚舉每個點的長,取最大值
一樣算最高的,先算出:atlas[i][j]*dn[1]+1(其中atlas爲輸入的矩陣數據),算出的是粉線部分,而後(n-i+1)這個表示的是第幾排(由於數組是:↓→這樣存儲的,可是實際上咱們要畫的是↑→的圖,所以要減一下)對於第(n-i+1)排,它的上面對長的貢獻就是dn[3]*(n-i+1)(這裏再也不加一是由於有一個點前面和上面都有貢獻,咱們只須要加一次(綠點處)),也就是每一個方塊對長貢獻2;(固然要枚舉取最高的)
而後考慮一張圖,咱們按照透視的順序,從後往前,從左往右的依次添加覆蓋,首先是最左下的立方體(其實通常會被所有覆蓋掉,但咱們仍是要加),而後咱們固定一個點,爲立方體的定位點,以此點爲基礎拓展出整個立方體,因此最關鍵的一點就是定位立方體了:
這裏定位立方體的左下角:
而後就是咋的定位了,
而後咱們仍是看個樣例:(啊算了,我補不出來(艱難))
(百度網圖qwq)
而後你看這個圖,輸入的數據中爲atlas[1][1]的立方體的左下角就是紅點標出的地方,而後咱們求出的nn是綠色線標出的地方,mm是紫色線標出的地方,這樣咱們在存二維數組時,先存最左下角的立方體:
求某個立方體左下角座標:
對於x(與nn(長)同方向的那個),咱們顯然只須要考慮dn對其的影響;(上下)
而後由於咱們的思路是:
求出紅點的在二維平面的座標,而後給對於每一個立方體上面再摞立方體。
因此不用把層數>=2的左下角求出來;
回到這個圖:
咱們應該如何求這個點的x呢??
先放代碼(由於發現莫得代碼不知道咋的講):
for(int i=1;i<=n;i++){ for(int j=1,x,y;j<=m;j++){ x=nn-dn[3]*(n-i); y=dm[3]*(n-i)+dm[2]*(j-1)+1; zhetizhenduliu(i,j,x,y); } }
根據咱們樓上的經驗,對於每一橫行來講,每向後放置一個立方體,對應點的x就會+dn[3],所以咱們在計算x時,考慮這個立方體相對於第一排立方體向後挪了幾個,由於數組atlas[1][i]其實對應的是最後一行,因此咱們覆蓋是從1↓m,1→n。(n-i)表示的就是咱們從第一行向後放了幾個立方體到達了咱們當前要放立方體的這一行,樓上紅點就是3-1,表示咱們在放這個方塊以前已經放了兩個方塊,每放一個方塊,x就要相對於綠線 所在地方向後dn[3](2)個,由於綠線是最大的位置,因此實際咱們須要用nn-(n-i)*dn[3];
而後對於y(與mm方向相同)(寬)
啊又要畫圖
仍是先推第一排的立方體,假設j=2(先無論i了在這不重要)
那麼很顯然這個點首先要計算的仍是第一排的位置,也就是(j-1)*dm[2]+1(每左右放一個方塊增長4,由於咱們求的是左下角,因此不能用j乘而是要用(j-1)乘(而後別忘了+1)。
而後再算先後擺放形成的影響,也是一樣,對於先後擺放,每擺放一個,左下角的位置向右挪2,而後也是從後往前記得編號嘛,因此仍是要用(n-i)*dm[3];
而後定位好了左下角,咱們能夠嘗試開始覆蓋了:
inline void zhetizhenduliu(int i,int j,int x,int y){ //x,y表示咱們定位點的左下角座標,i,j表示咱們定位點應該是輸入矩陣的哪個座標; int a,b; while(atlas[i][j]--){ for(a=0;a<6;a++) for(b=0;b<7;b++) if(s1[6-a-1][b]!='.') s[x-a][y+b]=s1[6-a-1][b]; x-=3; } }
而後忘記講的一件事,咱們要先將立方體打好表:
char s1[6][8]= { "..+---+", "./ /|", "+---+ |", "| | +", "| |/.", "+---+.." };//真好看的說
而後你看這是個6*7的表,但開了6*8,你開6*7會炸,由於對於字符串, 除了你存的字符外,它會再存入一個我也忘了叫啥的某個東西,所以咱們要多開一個;
而後覆蓋:
首先要講的是,咱們只計算了最底層的立方體的左下角位置,而後是向上摞立方體,當咱們每向上摞一個立方體時,長就 -=3;(由於咱們輸出是從上往下輸出,因此越靠近輸出的最上方的立方體的長其實越小,也就是須要 -=3而不是+=3的緣由)這是最外層while循環;
咱們計算出來的(x,y)實際上對應到s1數組中是s1[6][0];
用s數組存最終覆蓋後的答案,那麼注意要判斷的是s1[i][j](表示s1數組中某一個位置)!='.'或許你會像我同樣開始時認爲沒什麼用,可是若是你不加這一句:
你就wa聲一片了;
注意的是,這裏s數組是從1開始存的,而s1數組是從0開始存的;
而後應該能夠理解的吧,由於咱們定位的是左下角,因此對於其餘任意一個點,均可以由左下角的點的座標加加減減得出,並且對於長,必定是減,對於寬,必定是加(加減均包括0),而後就枚舉就好啦;
附上ych小蒟蒻皮皮魚的神仙代碼:
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<algorithm> #include<cmath> #include<queue> using namespace std; inline int read() { int ans=0; char last=' ',ch=getchar(); while(ch<'0'||ch>'9') last=ch,ch=getchar(); while(ch>='0'&&ch<='9') ans=(ans<<1)+(ans<<3)+ch-'0',ch=getchar(); if(last=='-') ans=-ans; return ans; } int n,m; char s1[6][8]= { "..+---+", "./ /|", "+---+ |", "| | +", "| |/.", "+---+.." }; int dm[4]= {0,0,4,2}; int dn[4]= {0,3,0,2}; char s[1000][1000]; int atlas[51][51]; int mm,nn; inline void zhetizhenduliu(int i,int j,int x,int y) { int a,b; while(atlas[i][j]--) { for(a=0; a<6; a++) for(b=0; b<7; b++) if(s1[6-a-1][b]!='.') s[x-a][y+b]=s1[6-a-1][b]; x-=3; } } int main() { n=read(),m=read(); for(int i=1; i<=1000; i++) for(int j=1; j<=1000; j++) s[i][j]='.'; for(int i=1; i<=n; i++) for(int j=1; j<=m; j++) atlas[i][j]=read(); mm=7+(n-1)*dm[3]+(m-1)*dm[2]; for(int i=1; i<=n; i++) for(int j=1; j<=m; j++) nn=max(nn,atlas[i][j]*dn[1]+dn[3]*(n-i+1)+1); for(int i=1; i<=n; i++) { for(int j=1,x,y; j<=m; j++) { x=nn-dn[3]*(n-i); y=dm[3]*(n-i)+dm[2]*(j-1)+1; zhetizhenduliu(i,j,x,y); } } for(int i=1; i<=nn; i++) { for(int j=1; j<=mm; j++) { printf("%c",s[i][j]); } puts(""); } return 0; }
end-