背景:
嗯~,这道题其实是我在学暴力的时候看到的,嗯,没错,就是学习暴力。没学的时候感觉这种东西肯定不用学呀,接触之后才发现自己原来是个连暴力都不会的菜鸡,其实这个题中也有好多我原来不知道或没有想到的用法。
好了,言归正传。
题目大意:
图1
图2
主要想法
做完之后还是对比了一下某份答案,虽然思路上差不多,但从代码实现感觉还是有点不一样,也各有千秋,就在这里一并介绍了吧。
思路其实还是比较直接的,就是先给每一个空编号(见图2),接着把每一种合法的方法都表示出来,然后再一个一个检验是否满足条件,然后就可以得出答案了。因为旋转的关系结果要除5,而因为对称也要除2,两者互不影响,所以结果总共要除10。
先展示一下我自己的代码:(5行全部相加,每一个空都被算了两次,总和为120,分到每个为24)
#include<bits/stdc++.h>
using namespace std;
int main()
{
int b,c=0,a[10]={1,2,3,4,5,6,8,9,10,12};
do
{
b=0;
if(a[1]+a[2]+a[3]+a[4]==24)b++;
if(a[4]+a[6]+a[7]+a[8]==24)b++;
if(a[0]+a[2]+a[5]+a[8]==24)b++;
if(a[0]+a[3]+a[6]+a[9]==24)b++;
if(a[1]+a[7]+a[5]+a[9]==24)b++;
if(b==5)c++;
}while(next_permutation(a,a+10));
cout<<c/10<<endl;
}
两个因为思路相同就不展示它的了。仅展示两者不同之处。
首先,是它对于每一行的定义不同,它用到了宏替换,这个东西其实我知道,只是一般都不会想到,只是在定义大数的时候用一下,没有考虑到它更接地气的价值。
#define A (star[1]+star[3]+star[6]+star[9]);
#define B (star[1]+star[4]+star[8]+star[10]);
#define C (star[2]+star[3]+star[4]+star[5]);
#define D (star[2]+star[6]+star[7]+star[10]);
#define E (star[5]+star[7]+star[8]+star[9]);
其次是它直接表示了这个全排列,让我也知道了一般全排列的实现方法(这里展示的是计数,而非直接解答)。
最后就是它宏定义了一个函数,今天真是颠覆了我对宏代换的认识。/笑哭!!!
int star[]={0,1,2,3,4,5,6,8,9,10,12}; //0不用
#define Swap(a,b) {int temp = a; a = b; b = temp;} //交换
int num=0; //统计全排列的个数,验证是不是3628800
int Perm(int begin,int end)
{
int i;
if(begin == end) // 结束,输出一个全排列
num++; //统计全排列的个数;
else
for(i = begin;i <= end;i++)
{
Swap(star[begin],star[i]);//交换位置,逐步前提
Perm(begin+1,end);
Swap(star[begin],star[i]);//将位置还回去,对下一次排列负责
}
}
int main()
{ Perm(1,10); //求从第1个数到第10个数的全排列。
cout<<num<<"\n"; //打印出排列总数,应该是3628800。
}