http://oj.ecustacm.cn/problem.php?id=1265
本题用现有的全排列函数计算时间太长,我大致的试了试有很长时间都没有出来答案。
只能用dfs + 剪枝来做此题。
思路已经有现有的大佬写好了。
这里就直接引用了。
自己写的代码:
#include<cstdio>
#include<string>
#include<iostream>
#define N 20
using namespace std;
int a[N][N];
bool b[17];
int ans=0;
bool check1(int n)
{
int sum=0;
for(int i=0;i<=3;i++)//行
{
sum+=a[n][i];
}
if(sum==34)
return true;
else
return false;
}
bool check()
{
int sum=0;
for(int i=0;i<=3;i++)//列
{
sum=a[0][i]+a[1][i]+a[2][i]+a[3][i];
if(sum!=34)
return false;
sum=0;
}
for(int i=0;i<=3;i++)//行
{
if(!check1(i))
{
return false;
}
}
sum=0;
sum=a[0][0]+a[1][1]+a[2][2]+a[3][3];//左对角
if(sum!=34)
return false;
sum=0;
sum=a[0][3]+a[1][2]+a[2][1]+a[3][0];//右对角线
if(sum!=34)
return false;
return true;
}
void dfs(int index)
{
if(index==16)
{
if(check())
ans++;
}
if(index%4==0)//说明当前的数够一行了,判断这一行
{
if(!check1(index/4-1))
{
return;
}
}
for(int i=2;i<=16;i++)
{
if(!b[i])
{
b[i]=true;
a[index/4][index%4]=i;
dfs(index+1);
b[i]=false;
}
}
}
int main(void)
{
a[0][0]=1;
dfs(1);
cout<<ans<<endl;
//cout<<416<<endl;
return 0;
}
#include<cstdio>
#include<iostream>
using namespace std;
int ans;
int a[20];
bool b[20];
void dfs(int index)
{
if(index==4) //第一行
{
int sum=0;
for(int i=0;i<4;i++)
sum+=a[i];
if(sum!=34) return;
}
if(index==8)//第二行
{
int sum=0;
for(int i=4;i<8;i++)
sum+=a[i];
if(sum!=34) return;
}
if(index==12)//第三行
{
int sum=0;
for(int i=8;i<12;i++)
sum+=a[i];
if(sum!=34) return;
}
if(index==16)//第四行
{
int sum=0;
for(int i=12;i<16;i++)
sum+=a[i];
if(sum!=34) return;
sum=0;
sum=a[3]+a[7]+a[11]+a[15];//第四列
if(sum!=34) return;
}
if(index==13) //第一列
{
int temp=a[0]+a[4]+a[8]+a[12];
if(temp!=34)
return ;
}
if(index==14) //第二列
{
int temp=a[1]+a[5]+a[9]+a[13];
if(temp!=34)
return ;
}
if(index==15) //第三列
{
int temp=a[2]+a[6]+a[10]+a[14];
if(temp!=34)
return ;
}
if(index==16) //对角线
{
int s1=a[0]+a[5]+a[10]+a[15];
int s2=a[3]+a[6]+a[9]+a[12];
if(s1==34&&s2==34)
ans++;
}
for(int i=2;i<=16;i++)
{
if(!b[i])
{
b[i]=true;
a[index]=i;
dfs(index+1);
b[i]=false;
}
}
}
int main(void)
{
a[0]=1;
dfs(1);
cout<<ans;
return 0;
}
总结: 难点部分在于坐标部分 和 剪枝判断部分。