免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12
最近访问板块 发新帖
楼主: Forif
打印 上一主题 下一主题

[算法] 问个数学上的问题 [复制链接]

论坛徽章:
14
巨蟹座
日期:2013-11-19 14:09:4615-16赛季CBA联赛之青岛
日期:2016-07-05 12:36:0515-16赛季CBA联赛之广东
日期:2016-06-29 11:45:542015亚冠之全北现代
日期:2015-07-22 08:09:472015年辞旧岁徽章
日期:2015-03-03 16:54:15巨蟹座
日期:2014-12-29 08:22:29射手座
日期:2014-12-05 08:20:39狮子座
日期:2014-11-05 12:33:52寅虎
日期:2014-08-13 09:01:31巳蛇
日期:2014-06-16 16:29:52技术图书徽章
日期:2014-04-15 08:44:01天蝎座
日期:2014-03-11 13:06:45
11 [报告]
发表于 2013-04-24 16:11 |只看该作者
6个数字的全排列有 6! 种,每一种用一个序号替代(序号为0到719)

假设第一行置为 1 2 3 4 5 6 的可能有 M 个,则最终结果为 M * 6!

假设第二行到第六行分别是序号a b c d e的排列
若假设 a b c d e 的序号是递增的情况下有 K 种可能,则最终结果为 K * 5! * 6!

求K只能使用暴力了,上代码(结果写在代码的注释中)
  1. #include <iostream>
  2. #include <bitset>
  3. #include <vector>
  4. #include <stack>
  5. #include <algorithm>

  6. template<size_t N> struct factorial // 阶乘
  7. {
  8.     static const size_t val = N * factorial<N-1>::val;
  9. };
  10. template<> struct factorial<1>
  11. {
  12.     static const size_t val = 1;
  13. };
  14. template<> struct factorial<0>
  15. {
  16.     static const size_t val = 1;
  17. };

  18. template<size_t N> unsigned long long foo( void )
  19. {
  20.     const size_t NP = factorial<N>::val;

  21.     std::vector< std::bitset<NP> > compatible_mash; // 不冲突的,且排在其后的排列的序号mask
  22.     {
  23.         struct permutation
  24.         {
  25.             char v[N]; // 排列

  26.             permutation( const char (&v_)[N] )
  27.             {
  28.                 std::copy( v_+0, v_+N, v );
  29.             }
  30.         };
  31.         // 全排列
  32.         std::vector<permutation> all_permutation;
  33.         all_permutation.reserve( NP );
  34.         {
  35.             char v[N];
  36.             for( size_t i=0; i!=N; ++i )
  37.                 v[i] = i+1;
  38.             do {
  39.                 all_permutation.push_back( v );
  40.             } while( std::next_permutation(v+0,v+N) );
  41.         }

  42.         // 计算不冲突的其他排列序号
  43.         compatible_mash.resize( NP );
  44.         for( size_t i=0; i!=NP; ++i )
  45.         {
  46.             for( size_t j=i+1; j!=NP; ++j )
  47.             {
  48.                 bool compatible = true;
  49.                 for( size_t k=0; k!=N; ++k )
  50.                 {
  51.                     if( all_permutation[i].v[k] == all_permutation[j].v[k] )
  52.                     {
  53.                         compatible = false;
  54.                         break;
  55.                     }
  56.                 }
  57.                 compatible_mash[i].set( j, compatible );
  58.             }
  59.         }
  60.     }

  61.     unsigned long long num = 0;
  62.     std::stack< std::pair< std::bitset<NP>, size_t > > mystack;
  63.     mystack.push( std::make_pair(compatible_mash[0],1) );
  64.     if( mystack.top().second == N )
  65.         ++num;
  66.     while( !mystack.empty() )
  67.     {
  68.         std::pair< std::bitset<NP>, size_t > one = mystack.top();
  69.         mystack.pop();

  70.         for( size_t i=0; i!=NP; ++i )
  71.         {
  72.             if( one.first.test(i) )
  73.             {
  74.                 if( one.second == N-1 )
  75.                 {
  76.                     ++num;
  77.                     if( num == 0 )
  78.                     {
  79.                         printf( "-------- bad --------\n" );
  80.                     }
  81.                     break;
  82.                 }
  83.                 std::bitset<NP> result = one.first & compatible_mash[i];
  84.                 if( result.any() )
  85.                 {
  86.                     mystack.push( std::make_pair(result,one.second+1) );
  87.                 }
  88.             }
  89.         }
  90.     }

  91.     return num * (NP/N) * NP;
  92. }

  93. using namespace std;

  94. int main()
  95. {
  96.     cout << "f(1) = " << foo<1>() << std::endl; // 1              = 1! * 0! * 1
  97.     cout << "f(2) = " << foo<2>() << std::endl; // 2              = 2! * 1! * 1
  98.     cout << "f(3) = " << foo<3>() << std::endl; // 12             = 3! * 2! * 1
  99.     cout << "f(4) = " << foo<4>() << std::endl; // 576            = 4! * 3! * 4
  100.     cout << "f(5) = " << foo<5>() << std::endl; // 161280         = 5! * 4! * 56
  101.     cout << "f(6) = " << foo<6>() << std::endl; // 812851200      = 6! * 5! * 9408
  102.     cout << "f(7) = " << foo<7>() << std::endl; // 61479419904000 = 7! * 6! * 16942080

  103.     return 0;
  104. }
复制代码

论坛徽章:
14
巨蟹座
日期:2013-11-19 14:09:4615-16赛季CBA联赛之青岛
日期:2016-07-05 12:36:0515-16赛季CBA联赛之广东
日期:2016-06-29 11:45:542015亚冠之全北现代
日期:2015-07-22 08:09:472015年辞旧岁徽章
日期:2015-03-03 16:54:15巨蟹座
日期:2014-12-29 08:22:29射手座
日期:2014-12-05 08:20:39狮子座
日期:2014-11-05 12:33:52寅虎
日期:2014-08-13 09:01:31巳蛇
日期:2014-06-16 16:29:52技术图书徽章
日期:2014-04-15 08:44:01天蝎座
日期:2014-03-11 13:06:45
12 [报告]
发表于 2013-04-25 16:36 |只看该作者
优化一下代码,可以将 f(7) 的耗时从860秒降低到53秒。可惜已经下班了,不想了,以后有空再研究
  1. #include <iostream>
  2. #include <bitset>
  3. #include <vector>
  4. #include <stack>
  5. #include <algorithm>
  6. #include <ctime>

  7. template<size_t N> struct factorial // 阶乘
  8. {
  9.     static const size_t val = N * factorial<N-1>::val;
  10. };
  11. template<> struct factorial<0>
  12. {
  13.     static const size_t val = 1;
  14. };

  15. template<size_t N> unsigned long long foo( void )
  16. {
  17.     if( N == 1 )
  18.         return 1;

  19.     const size_t NP = factorial<N>::val;

  20.     std::vector< std::bitset<NP> > compatible_mash; // 不冲突的,且排在其后的排列的序号mask
  21.     {
  22.         struct permutation
  23.         {
  24.             char v[N]; // 排列

  25.             permutation( const char (&v_)[N] )
  26.             {
  27.                 std::copy( v_+0, v_+N, v );
  28.             }
  29.         };
  30.         // 全排列
  31.         std::vector<permutation> all_permutation;
  32.         all_permutation.reserve( NP );
  33.         {
  34.             char v[N];
  35.             for( size_t i=0; i!=N; ++i )
  36.                 v[i] = i+1;
  37.             do {
  38.                 all_permutation.push_back( v );
  39.             } while( std::next_permutation(v+0,v+N) );
  40.         }

  41.         // 计算不冲突的其他排列序号
  42.         compatible_mash.resize( NP );
  43.         for( size_t i=0; i!=NP; ++i )
  44.         {
  45.             for( size_t j=i+1; j!=NP; ++j )
  46.             {
  47.                 bool compatible = true;
  48.                 for( size_t k=0; k!=N; ++k )
  49.                 {
  50.                     if( all_permutation[i].v[k] == all_permutation[j].v[k] )
  51.                     {
  52.                         compatible = false;
  53.                         break;
  54.                     }
  55.                 }
  56.                 compatible_mash[i].set( j, compatible );
  57.             }
  58.         }
  59.     }

  60.     unsigned long long num = 0;

  61.     std::stack< std::pair< std::bitset<NP>, size_t > > mystack;
  62.     mystack.push( std::make_pair(compatible_mash[0],1) );
  63.     while( !mystack.empty() )
  64.     {
  65.         std::pair< std::bitset<NP>, size_t > one = mystack.top();
  66.         mystack.pop();

  67.         for( size_t i=NP/N*one.second; i!=NP/N*one.second+NP/N; ++i )
  68.         {
  69.             if( one.first.test(i) )
  70.             {
  71.                 if( one.second == N-1 )
  72.                 {
  73.                     ++num;
  74.                     if( num == 0 )
  75.                     {
  76.                         printf( "-------- bad --------\n" );
  77.                     }
  78.                     break;
  79.                 }
  80.                 std::bitset<NP> result = one.first & compatible_mash[i];
  81.                 if( result.any() )
  82.                 {
  83.                     mystack.push( std::make_pair(result,one.second+1) );
  84.                 }
  85.             }
  86.         }
  87.     }

  88.     return num * (NP/N) * NP;
  89. }

  90. using namespace std;

  91. int main()
  92. {
  93.     time_t tb = time( NULL );
  94.     cout << "f(1) = " << foo<1>() << std::endl; // 1              = 1! * 0! * 1
  95.     cout << "f(2) = " << foo<2>() << std::endl; // 2              = 2! * 1! * 1
  96.     cout << "f(3) = " << foo<3>() << std::endl; // 12             = 3! * 2! * 1
  97.     cout << "f(4) = " << foo<4>() << std::endl; // 576            = 4! * 3! * 4
  98.     cout << "f(5) = " << foo<5>() << std::endl; // 161280         = 5! * 4! * 56
  99.     cout << "f(6) = " << foo<6>() << std::endl; // 812851200      = 6! * 5! * 9408
  100.     cout << "f(7) = " << foo<7>() << std::endl; // 61479419904000 = 7! * 6! * 16942080
  101.     time_t te = time( NULL );
  102.     cout << "elapsed time: " << (te-tb) << endl; // 53

  103.     return 0;
  104. }
复制代码

论坛徽章:
14
巨蟹座
日期:2013-11-19 14:09:4615-16赛季CBA联赛之青岛
日期:2016-07-05 12:36:0515-16赛季CBA联赛之广东
日期:2016-06-29 11:45:542015亚冠之全北现代
日期:2015-07-22 08:09:472015年辞旧岁徽章
日期:2015-03-03 16:54:15巨蟹座
日期:2014-12-29 08:22:29射手座
日期:2014-12-05 08:20:39狮子座
日期:2014-11-05 12:33:52寅虎
日期:2014-08-13 09:01:31巳蛇
日期:2014-06-16 16:29:52技术图书徽章
日期:2014-04-15 08:44:01天蝎座
日期:2014-03-11 13:06:45
13 [报告]
发表于 2013-04-27 13:21 |只看该作者
这玩意儿叫“拉丁方阵” https://zh.wikipedia.org/wiki/拉丁方阵

n    a(n)
1    1
2    2
3    12
4    576
5    161280
6    812851200
7    61479419904000
8    108776032459082956800
9    5524751496156892842531225600
10   9982437658213039871725064756920320000
11   776966836171770144107444346734230682311065600000

论坛徽章:
0
14 [报告]
发表于 2013-05-02 12:32 来自手机 |只看该作者
bruce teenager?
谢了 帮了我不少忙 十分感谢!,-)
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP