传说中的越南小学数学题

前几天在微博上看到这个所谓的神题,然后就想着来算算
http://t.qq.com/p/t/487008033132809/14?&#p=2&select=1&time=1432732148&mid=466699120015199&apiType=14&format=1
全排列算法部分抄自:
http://blog.csdn.net/yangliuy/article/details/7555518
题目截图:
如果假设题目中填入的数字不允许重复,那么只要找到
list[0]+(13*list[1])/list[2]+list[3]+12*list[4]-list[5]-11+(list[6]*list[7])/list[8]-10=66的解即可。
然后难点就在于,如何确定这个list。
我先想到的是类似于四皇后的解法,也就是生成一个矩阵
1 1 1 1 1 1 1 1 1 1
2 2 2 2 2 2 2 2 2 2。。。。
然后每列选取一个,然后每一列都不重复即可。。。但是后面突然想到,这事儿没这么复杂,完全可以初始化一个数组
list[]={1,2,3,4,5,6,7,8,9};
然后求这个数组的全排列即可。然后就得到了下面的代码:

#include<iostream>
using namespace std;
//n用于记录解空间总数
int n=0;
void swap(int *a, int *b){     
     int m;     
     m = *a;     
     *a = *b;     
     *b = m; 
 }  

 void perm(int list[], int k, int m) 
 {     
     int i; 

     if(k > m)     
     {  int sum=0;  
     //这里是为了排除计算除法时导致的精度丢失的问题,只取能够整除的数据
        if((((13*list[1])%list[2])==0)&&((list[6]*list[7])%list[8]==0))
            sum=list[0]+(13*list[1])/list[2]+list[3]+12*list[4]-list[5]-11+(list[6]*list[7])/list[8]-10;    
        if(sum==66) {   
            for(i = 0; i <= m; i++)             
            cout<<list[i]<<" ";         
            cout<<endl;
            n++;  
        }

     }     
     else     
     {         
         for(i = k; i <= m; i++)         
         {             
             //传说这是全排列的核心,但是我没看懂。。。orz
             swap(&list[k], &list[i]);             
             perm(list, k + 1, m);             
             swap(&list[k], &list[i]);         
         }     
     } 
 } 
int main() 
 {     

    int list[] = {1,2,3,4,5,6,7,8,9};     
    perm(list, 0, 8);     
    cout<<"total: "<<n<<endl;     
    return 0; 
 }  

计算结果:
3 2 1 5 4 7 8 9 6
3 2 1 5 4 7 9 8 6
5 2 1 3 4 7 8 9 6
5 2 1 3 4 7 9 8 6
5 3 1 7 2 6 8 9 4
5 3 1 7 2 6 9 8 4
5 4 1 9 2 7 8 3 6
5 4 1 9 2 7 3 8 6
5 9 3 6 2 1 7 8 4
5 9 3 6 2 1 8 7 4
6 3 1 9 2 5 7 8 4
6 3 1 9 2 5 8 7 4
6 9 3 5 2 1 7 8 4
6 9 3 5 2 1 8 7 4
7 3 1 5 2 6 8 9 4
7 3 1 5 2 6 9 8 4
9 3 1 6 2 5 7 8 4
9 3 1 6 2 5 8 7 4
9 4 1 5 2 7 8 3 6
9 4 1 5 2 7 3 8 6
total: 20


Process exited after 3.832 seconds with return value 0
纯新手,欢迎指正^_^

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值