第四题
标题:幻方填空
题目描述:
幻方是把一些数字填写在方阵中,使得行、列、两条对角线的数字之和都相等。
欧洲最著名的幻方是德国数学家、画家迪勒创作的版画《忧郁》中给出的一个4阶幻方。
他把1,2,3,…16 这16个数字填写在4 x 4的方格中。
如图所示,即:
16 ? ? 13
? ? 11 ?
9 ? ? *
? 15 ? 1
表中有些数字已经显露出来,还有些用?和*代替。
请你计算出? 和 * 所代表的数字。并把 * 所代表的数字作为本题答案提交。
答案是一个整数,请通过浏览器直接提交该数字。
注意:不要提交解答过程,或其它辅助说明类的内容。
解题思路:
搜索(dfs)+剪枝 可以使用一个二维数组保存该幻方(预先没有填数的位置(包括?和*)为0),然后从第一个“0”开始(位置(0,
1))搜索,依次试探2~16 15个数(因为1已经预先填入幻方)。找到符合要求的解。注意标记及剪枝(这里使用了行剪枝,当搜索到第二行时,用flag记录第一行4个数的和,后面若发现某行4个数之和不等于flag,则该方案不符合要求),以提高程序效率。
代码:
#include <stdio.h>
#include <string.h>
#define maxn 20
int mat[4][4]={ //4*4幻方(0代表?或*)
{16,0,0,13},
{0,0,11,0},
{9,0,0,0},
{0,15,0,1}
};
int used[maxn]; //16个数的使用标记 1-已使用 0-未使用
int flag; //记录第一行4个数之和
int Judge(int mt[][4]) //判断各列与两条对角线之和是否与各行之和相等
{
int i,j;
int sumc,sumln1,sumln2;
//依次计算各列4个数之和
for(j=0;j<4;j++)
{
sumc=0;
for(i=0;i<4;i++)
sumc+=mt[i][j];
//若sumc不等于flag,则方案不成立
if(sumc!=flag)
return 0;
}
//计算两条对角线上4个数之和
sumln1=sumln2=0;
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
{
//主对角线
if(i==j)
sumln1+=mt[i][j];
//副对角线
if(i==4-j-1)
sumln2+=mt[i][j];
}
}
//若sumln1或sumln2不等于flag,则方案不成立
if(sumln1!=flag || sumln2!=flag)
return 0;
//否则方案成立
return 1;
}
void dfs(int x,int y,int cursumr)
{
int i,j,num;
//搜索终点
if(x==3 && y==4)
{
if(Judge(mat))
{
for(i=0;i<4;i++)
{
for(j=0;j<3;j++)
printf("%d ",mat[i][j]);
printf("%d\n",mat[i][3]);
}
}
return;
}
//一行搜索结束:继续搜索下一行
if(y==4)
dfs(x+1,0,0);
//(x,y)已填入数字,则继续搜索下一位置(x,y+1)
if(mat[x][y]!=0)
dfs(x,y+1,cursumr+mat[x][y]);
//计算第一行4个数之和,并以此作为后续判断的标记
if(x==1 && y==0)
{
flag=0;
for(j=0;j<4;j++)
flag+=mat[0][j];
}
//依次试探2-16 15个数
for(num=2;num<=16;num++)
{
//当前位置(x,y)没有填数,并且num未使用
if(mat[x][y]==0 && !used[num])
{
//行剪枝:搜索到每行最后一个数时,若发现cursumr+待填数num不等于flag
//则num无法填入,应试探下一个数num+1
if(x>=1 && y==3 && cursumr+num!=flag)
continue;
//填入
used[num]=1;
mat[x][y]=num;
//搜索下一位置
dfs(x,y+1,cursumr+mat[x][y]);
//回溯
used[num]=0;
mat[x][y]=0;
}
}
}
int main()
{
//初始化
memset(used,0,sizeof(used));
//1.9.11.13.15.16已填入幻方,因此置used标记1
used[1]=1,used[9]=1,used[11]=1;
used[13]=1,used[15]=1,used[16]=1;
//从第一个问号(0,1)处开始搜索
dfs(0,1,16);
return 0;
}
运行结果:
16 3 2 13
5 10 11 8
9 6 7 12
4 15 14 1
答案:
12