给出4*4的网格平面,要求在这个16个格子里面放入楼层分别是1、2、3、4层高的楼栋;
要求每行以及每列的1~4层楼必须且只能出现一次;
给出条件是从每个方向上所能看到的不被遮挡的楼栋数目;
Example:
To understand how the puzzle works, this is an example of a row with 2 clues. Seen from the left side there are 4 buildings visible while seen from the right side only 1: 
There is only one way in which the skyscrapers can be placed. From left-to-right all four buildings must be visible and no building may hide behind another building:

Example of a 4 by 4 puzzle with the solution:

代码(我这个是用穷举的方法来做的,先算出4!一共24种组合,然后依次遍历,其实比较笨,应该有更聪明的方法,以后有空了想想):
typedef struct _AssNode{
int Valuegroup[4];
int LeftViewCnt;
int RightViewCnt;
}AssNode;
int GetLeftViewCnt(int *Buff, int Sz){
int i, j;
int Cnt = Sz;
if(Sz < 2) return Sz;
/*从第二个数开始遍历,如果他前面有数比他大,说明被遮挡,返回值-1*/
for(i=1; i<Sz; i++){
for(j=0; j<i; j++){
if(Buff[j] > Buff[i]){
Cnt--;
break;
}
}
}
return Cnt;
}
int GetRightViewCnt(int *Buff, int Sz){
int i, j;
int Cnt = Sz;
if(Sz < 2) return Sz;
/*从倒数第二个数开始遍历,如果他后面有数比他大,说明被遮挡,返回值-1*/
for(i=Sz-2; i>=0; i--){
for(j=Sz-1; j>i; j--){
if(Buff[j] > Buff[i]){
Cnt--;
break;
}
}
}
return Cnt;
}
int Get4X4Assemble(AssNode *Assemble){
int i, j, k, z;
int cnt = 0;
for(i=1; i<=4; i++){
for(j=1; j<=4; j++){
if(j == i)continue;
for(k=1; k<=4; k++){
if(k == i || k == j)continue;
for(z=1; z<=4; z++){
if(z == i || z == j || z == k)continue;
Assemble[cnt].Valuegroup[0] = i;
Assemble[cnt].Valuegroup[1] = j;
Assemble[cnt].Valuegroup[2] = k;
Assemble[cnt].Valuegroup[3] = z;
Assemble[cnt].LeftViewCnt = GetLeftViewCnt(Assemble[cnt].Valuegroup, 4);
Assemble[cnt].RightViewCnt = GetRightViewCnt(Assemble[cnt].Valuegroup, 4);
cnt++;
}
}
}
}
}
/*判断数组列是否是1'2'3'4的组合*/
int IsColumeOrder(int ** buff){
int i, j;
int cnt = 0;
for(j=0; j<4; j++){
cnt = 0;
for(i=1; i<=4; i++){
if((*buff)[j] == i
|| (*(buff+1))[j] == i
|| (*(buff+2))[j] == i
|| (*(buff+3))[j] == i){
cnt++;
}
}
if(cnt != 4){
return 0;
}
}
return 1;
}
int** SolvePuzzle (int *clues) {
AssNode Assemble[24];
int **out;
int colbuf[4] = {0};
int col;
int i,j,k,z;
int ii,jj;
//printf("AAA\n");
out = malloc(sizeof(int*) * 4);
for(i=0; i<4; i++){
*(out+i) = malloc(sizeof(int) * 4);
}
Get4X4Assemble(Assemble);
/*第一行*/
for(i=0; i<24; i++){
/*找到一个符合行要求的组合*/
if((clues[15] == 0 || Assemble[i].LeftViewCnt == clues[15])
&& (clues[4] == 0 || Assemble[i].RightViewCnt == clues[4])){
memcpy(*out, Assemble[i].Valuegroup, 4*sizeof(int));
//printf("AAb\n");
/*第二行*/
for(j=0; j<24; j++){
/*找到一个符合行要求的组合*/
if((clues[14] == 0 || Assemble[j].LeftViewCnt == clues[14])
&& (clues[5] == 0 || Assemble[j].RightViewCnt == clues[5])){
memcpy(*(out+1), Assemble[j].Valuegroup, 4*sizeof(int));
/*第三行*/
for(k=0; k<24; k++){
/*找到一个符合行要求的组合*/
if((clues[13] == 0 || Assemble[k].LeftViewCnt == clues[13])
&& (clues[6] == 0 || Assemble[k].RightViewCnt == clues[6])){
memcpy(*(out+2), Assemble[k].Valuegroup, 4*sizeof(int));
//printf("AAc\n");
/*第四行*/
for(z=0; z<24; z++){
/*找到一个符合行要求的组合*/
if((clues[12] == 0 || Assemble[z].LeftViewCnt == clues[12])
&& (clues[7] == 0 || Assemble[z].RightViewCnt == clues[7])){
memcpy(*(out + 3), Assemble[z].Valuegroup, 4*sizeof(int));
/*校验列是否正确*/
if(!IsColumeOrder(out)) continue;
for(col=0; col<4; col++){
colbuf[0] = out[0][col];
colbuf[1] = out[1][col];
colbuf[2] = out[2][col];
colbuf[3] = out[3][col];
//printf("AAd\n");
if(!((clues[col] == 0 || clues[col] == GetLeftViewCnt(colbuf, 4))
&& (clues[11-col] == 0 || clues[11-col] == GetRightViewCnt(colbuf, 4)))){
/*校验列不正确,终止校验*/
/*printf("Err: i=%d, j=%d, k=%d, z=%d\n", i,j,k,z);
printf("Err: Left=%d, right=%d, clues[col]=%d, clues[11-col]=%d\n",
GetLeftViewCnt(colbuf, 4),GetRightViewCnt(colbuf, 4), clues[col], clues[11-col]);
for(ii=0; ii<4; ii++){
for(jj=0; jj<4; jj++){
printf("%d ", out[ii][jj]);
}
printf("\n");
}*/
break;
}
}
if(col == 4){
/*找到答案,返回*/
/*printf("Get: i=%d, j=%d, k=%d, z=%d\n", i,j,k,z);
for(ii=0; ii<4; ii++){
for(jj=0; jj<4; jj++){
printf("%d ", out[ii][jj]);
}
printf("\n");
}*/
return out;
}
}
}
}
}
}
}
}
}
//printf("return 0: i=%d, j=%d, k=%d, z=%d\n", i,j,k,z);
return 0;
}
本文探讨了4*4网格上的摩天大楼拼图问题,要求每行和每列的楼层数唯一。通过举例说明解题思路,并提供了一种使用穷举法的C语言实现,尽管效率不高,但能有效找到解决方案。未来计划探索更优化的算法方法。

530

被折叠的 条评论
为什么被折叠?



