Topcoder_2_157

【问题描述】
    数组a[1], a[2], ... a[k*n]是一个k阶的循环数组,即数组的数字是1至n,循环k次。在该数组中如果任意紧邻的2个元素不相同,就定义其为“不友好的”,例如2阶数组 (1, 2, 3, 2, 1, 3)就是“不友好的”,但是(1, 2, 2, 3, 1, 3)不是。
    题目中给定n和k,需要求出k阶n维数组中所有“不友好的”数组的个数。

  定义:
类  UnfriendlyMultiPermutation
方法  public int count(int n, int k)

  约束:
1、n取值范围为1至20;
2、k取值范围为1至5。

  测试用例:
1、2    2    Returns: 2
2、3    2    Returns: 30
3、5    1    Returns: 120
4、2    4    Returns: 2
  1. public class UnfriendlyMultiPermutation {
  2.     /**
  3.      * 使用递归的方式对数组进行排列,剔除掉不符合要求的排列得到符合要求的数量。
  4.      * 然后再删除重复的排列,方法就是除以重复的次数得到就是所有不重复的数量。
  5.      * 例如:对于n=2,k=4
  6.      * 合法的排列是"1 2 1 2 1 2 1 2"和"2 1 2 1 2 1 2 1",对于第一个串因为第1、3、5、7位置上
  7.      * 的1会造成结果的重复(2同样有此问题),所以应该除以4!×4!(4!=4×3×2×1)来剔除掉重复的数量。
  8.      */
  9.     private int[] numArray;
  10.     private int count = 0;
  11.     public int count(int n, int k) {
  12.         numArray = new int[k * n];
  13.         int[] flag = new int[k * n];
  14.         for (int i = 0; i < n; i++)
  15.             for (int x = 0; x < k; x++)
  16.                 numArray[i * k + x] = i + 1;
  17.         
  18.         calCount(flag, 0);
  19.         int fun = 1;
  20.         for (int i = 2; i <= k; i++){
  21.             fun *= i;
  22.         }
  23.         return count / ((int) Math.pow(fun, n));
  24.     }
  25.     private void calCount(int[] flag, int lastNum) {
  26.         boolean isOver = true;
  27.         for (int i = 0; i < flag.length; i++) {
  28.             if (flag[i] == 0) {
  29.                 flag[i] = 1;
  30.                 isOver = false;
  31.                 if (lastNum != numArray[i]) {
  32.                     calCount(flag, numArray[i]);
  33.                 }
  34.                 flag[i] = 0;
  35.             }
  36.         }
  37.         if (isOver) {
  38.             count++;
  39.         }
  40.     }
  41. }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值