這個拼圖遊戲要求將一些圖形拼成一個正方形,圖形的個數從1到5。如下圖所示,圖形個數是4。
圖形不能旋轉,拼的時候不能重疊,拼完後的正方形裏面不能有空隙。所有給定的圖形都要使用。
左面的圖表示這樣拼不行,右面是一個成功的拼法。
現在,@潘帕斯雄鷹想知道他能否完成這個遊戲以表示自己是最強的鷹;如果可以,請輸出一種完成這個遊戲的方案。
輸入格式:
文件的第一行是一個整數n,表示圖形的個數,範圍從1到5。
接下來有n個部分,每個部分的第一行是2個整數i和j,表示下面的i行j列用來描述一個圖形。圖形用0和1表示,1表示圖形佔有這個位置,0表示不佔有,中間沒有空格。例如上圖中圖形A的描述是
2 3
111
101
所有圖形的長與寬都不超過5。
根據圖形給出的順序給每個圖形編號,從1開始,至多到5。
保證數據無多解情況。
輸出文件:
如果不能拼成一個正方形,就輸出“No solution possible”;否則,輸出一種拼的方案:一個正方形的數陣,每個位置上的數字是佔有這個位置的圖形的編號,中間沒有空格。例如上面A、B、C、D的編號依次是1、2、3、4,那麼就可以輸出
1112
1412
3422
3442
輸入樣例1:
4
1 4
1111
1 4
1111
1 4
1111
2 3
111
001
輸出樣例1:
No solution possible
輸入樣例2:
5
2 2
11
11
2 3
111
100
3 2
11
01
01
1 3
111
1 1
1
輸出樣例2:
1133
1153
2223
2444
爆搜回溯“好題”
#include<bits/stdc++.h>
#define V ((int)sqrt(res))
using namespace std;
int n,x[10],y[10],a[100][100],Map[100][100][10],res=0;
inline bool pd(int xx,int yy,int k){
for(int i=1;i<=x[k];i++)
for(int j=1;j<=y[k];j++)
if(a[i+xx-1][j+yy-1]&&Map[i][j][k])
return false;
return true;
}inline void dfs(int k){
if(k==n+1){
for(int i=1;i<=V;i++){
for(int j=1;j<=V;j++)
printf("%d",a[i][j]);
puts("");
}
exit(0);//搜到結果輸出後直接跳掉
}for(int i=1;i<=V;i++)
for(int j=1;j<=V;j++)//枚舉左上角
if(pd(i,j,k)){//判斷是否可以放上這個圖形
for(int l=1;l<=x[k];l++)
for(int r=1;r<=y[k];r++)
a[l+i-1][r+j-1]+=Map[l][r][k]*k;//放上該圖形
dfs(k+1);
for(int l=1;l<=x[k];l++)
for(int r=1;r<=y[k];r++)
a[l+i-1][r+j-1]-=Map[l][r][k]*k;//回溯
}
}int main(){char ch;
//freopen("puzzling.in","r",stdin);
//freopen("puzzling.out","w",stdout);
scanf("%d",&n);for(int i=0;i<=200;i++)
for(int j=0;j<=200;j++){
a[i][j]=1; //這裏定了邊界
}for(int i=1;i<=n;i++){
scanf("%d%d",&x[i],&y[i]);
for(int j=1;j<=x[i];j++)for(int k=1;k<=y[i];k++){
cin>>ch;Map[j][k][i]=ch^48;
if(Map[j][k][i])res+=1;//Map[j][k][i]表示第i個圖形(j,k)位置爲1
}
}if(res==1){
puts("1");exit(0);//這句特判是需要的,有可能會有許多0中間一個1的毒瘤數據
}if(V*V!=res){
puts("No solution possible");
exit(0);
}for(int i=1;i<=V;i++)
for(int j=1;j<=V;j++){
a[i][j]=0;
}dfs(1);//從第一個圖形開始搜索
puts("No solution possible");
return 0;
}