首页 > 代码库 > [解题报告][搜索+剪枝技巧]幻方

[解题报告][搜索+剪枝技巧]幻方

【Description】
请解决一个 N 阶幻方。(N=3或4)
为了凑够 15 字补一个幻方的简介好了。给定 N*N 个数,把它们填入 N*N 的方格中,使每
行每列和两个斜对角线里数的和都相等。
【Input】
第一行一个正整数 N
第二行 N*N 个整数,代表要填入幻方中的数
【Output】
N 行每行 N 个整数,用空格隔开,代表填好的幻方。
如果有多组解,输出任意一组即可。
保证有解。
【Sample Input1】
3
9 9 9 9 9 9 9 9 9
【Sample Output1】
9 9 9
9 9 9
9 9 9
【Sample Input2】
3
1 2 3 4 5 6 7 8 9
【Sample Output2】
2 7 6
9 5 1
4 3 8

思路:

 1.如果n=3,可以暴力枚举,复杂度为O(9!)

 2.n=4时,直接暴力4*4的话一定会挂,可以只暴力8个格子

          # # # #

          # 1 # 8

          # 6 2 7

          # 5 4 3

剪枝1:只搜8个格子(上)

剪枝2:按照一定的顺序搜索,当搜索到一些特定的格子就能推算出某个#的数值,如果#不在可用数字范围内,可以直接return

优化1:记录每个数字出现的个数,判断是否在可用范围内时直接判断个数,注意最好不要用map(似乎会消耗大量时间),可以用unordered_map或者自己离散化。

幻方和=所有数字总和/n

 

代码:

  1 #include <cstdio>  2 #include <cstdlib>  3 #include <algorithm>  4 #include <map>  5 #include <ctime>  6 #include <cstring>  7 using namespace std;  8 int pl[20],use[20];  9 int n,pn,sum; 10 int hf[5][5]; 11 int mm[20],mmct[20]; 12 int mp=0; 13 #define covidx(x,y) (x-1)*4+(y-1) 14 void prints() 15 { 16     for(int i=1; i<=n; i++) 17         for(int j=1; j<=n; j++) 18             { 19                 printf("%d%c",hf[i][j],j==n?\n: ); 20             } 21 } 22 inline int getid(int a) 23 { 24     for(int i=0; i<mp; i++) 25         { 26             if(mm[i]==a) return i; 27         } 28     return 19; 29 } 30 inline int check() 31 { 32     int t1=0,t2=0,t3=0,t4=0; 33     for(int i=1; i<=n; i++) 34         { 35             t1+=hf[i][i]; 36             t2+=hf[i][n-i+1]; 37             for(int j=1; j<=n; j++) 38                 { 39                     t3+=hf[i][j]; 40                     t4+=hf[j][i]; 41                 } 42             if(t3!=t4 || t3!=sum || t4!=sum) return 0; 43             else if(i!=n) 44                 t3=t4=0; 45         } 46     if(t2!=t1) return 0; 47     if(t3!=t2) return 0; 48     if(t2!=sum) return 0; 49     return 1; 50 } 51 void fuck3(int x,int y) 52 { 53  54     if(x==4) 55         { 56             if(check()) 57                 { 58                     prints(); 59                     exit(0); 60                 } 61             else 62                 return; 63         } 64     int tx,ty; 65     for(int i=1; i<=pn; i++) 66         { 67             if(!use[i]) 68                 { 69                     use[i]=1; 70                     hf[x][y]=pl[i]; 71                     if(y==3) 72                         { 73                             ty=1; 74                             tx=x+1; 75                         } 76                     else 77                         { 78                             ty=y+1; 79                             tx=x; 80                         } 81                     fuck3(tx,ty); 82                     use[i]=0; 83                 } 84         } 85 } 86  87 /* 88  3 6 8 8 89 #7 1 8 8 90  7 6 2 7 91  5 5 4 3 92  93  1  2  3  4 94  5  6  7  8 95  9  10 11 12 96  13 14 15 16 97 */ 98 int xyidx[9][2]= {{-1,-1},{2,2},{3,3},{4,4},{4,3},{4,2},{3,2},{3,4},{2,4}}; 99 int deps[16][8]=100 {101     {1,2,3},{1,6,5},{-1,-2,-4},{8,7,3},102     {-1,-9,-13},{0},{-5,1,8},{0},103     {6,2,7},{0},{0},{0},104     {5,4,3},{0},{0},{0}105 };106 int lin[16][4]=107 {108     {0},{0},{0},{3},109     {0},{0},{4},{7},110     {5},{2},{0},{9},111     {0},{13},{0},{1}112 };113 114 115 116 int prelin(int idx)117 {118     int i,j;119     i=0;120     if(idx>0)121         idx=(xyidx[idx][0]-1)*4+xyidx[idx][1]-1;122     else123         idx=-idx;124     while(lin[idx][i]!=0)125         {126             int cpa=lin[idx][i];127             int x=(cpa-1)/4+1;128             int y=(cpa-1)%4+1;129             int nsum=0;130             j=0;131             cpa-=1;132             while(deps[cpa][j]!=0)133                 {134                     int dalao=deps[cpa][j],x,y;135                     if(dalao>0)136                         {137                             x=xyidx[dalao][0];138                             y=xyidx[dalao][1];139                         }140                     else141                         {142                             dalao=-dalao;143                             dalao-=1;144                             x=dalao/4+1;145                             y=dalao%4+1;146                         }147                     nsum+=hf[x][y];148                     j++;149                 }150             int id;151             if(mmct[id=getid(sum-nsum)]>0)152                 {153                     hf[x][y]=sum-nsum;154                     mmct[id]--;155                     prelin(-(covidx(x,y)));156                 }157             else158                 {159                     return 0;160                 }161             i++;162         }163     return 1;164 }165 void dfs4(int idx)166 {167     if(idx==9)168         {169             if(check())170                 {171                     prints();172                     exit(0);173                 }174             else175                 {176                     return;177                 }178         }179     //给idx填数180     int x=xyidx[idx][0];181     int y=xyidx[idx][1];182     int bnaive[20];183     memcpy(bnaive,mmct,sizeof(mmct));184     int id;185     for(int i=1; i<=pn; i++)186         {187             if(mmct[id=getid(pl[i])]>0)188                 {189                     mmct[id]--;190                     hf[x][y]=pl[i];191                     if(prelin(idx)==0)192                         {193                             memcpy(mmct,bnaive,sizeof(mmct));194                             continue;195                         }196                     dfs4(idx+1);197                     memcpy(mmct,bnaive,sizeof(mmct));198                 }199         }200 }201 int main()202 {203     //freopen("magicsquare.in","r",stdin);204     //freopen("magicsquare.out","w",stdout);205     scanf("%d",&n);206     pn=n*n;207     for(int i=1; i<=pn; i++)208         {209             scanf("%d",&pl[i]);210             sum+=pl[i];211         }212     sort(&pl[1],&pl[pn+1]);213     if(n==3)214         fuck3(1,1);215     else216         {217             sum/=4;218             for(int i=1; i<=pn; i++)219                 {220                     int id;221                     if((id=getid(pl[i]))==19)222                         {223                             mm[mp]=pl[i];224                             mmct[mp]=1;225                             mp++;226                         }227                     else228                         {229                             mmct[id]++;230                         }231                 }232             dfs4(1);233         }234 }

 

[解题报告][搜索+剪枝技巧]幻方