[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖
以下代码 在 Windows 7 64-bit, 处理器: Core i3-3110M CPU @ 2.40GHz (4 CPUs), ~2.4GHz
chrome 42.0 环境运行, 耗时 < 100ms.

得结果
1,11,2,1,1,1,1,1,1,1
1,7,3,2,1,1,1,2,1,1
  1. <html>
  2.     <body>
  3.         结果<br>
  4.         <textarea id="result" style="height: 100px; width: 300px;"></textarea><br/>
  5.         运行时间从 <span id="start"></span>--<span id="end"></span><br>
  6.         <button type="button" onclick="run();">运行</button>
  7.     </body>
  8. </html>
  9. <script>
  10. var g = new Array(10);
  11. var f = new Array(10);
  12. function run() {
  13.   time_shot('start');
  14.   init();
  15.   f_search(9, 30);
  16.   time_shot('end');
  17. }
  18. function init() {
  19.   for (var i = 0; i <= 9; i++) {
  20.     g[i] = 1;
  21.   }
  22. }
  23. function f_search(ind, fsum_rem) {
  24.   var t = ind - 2 >> 31;
  25.   var fi_up = t & 21 | ~t & Math.floor((19 + ind) / (t | (ind - 1)));
  26.   if (ind == 0 && fi_up > 3) {
  27.     fi_up = 3;
  28.   }
  29.   t = fsum_rem - ind;
  30.   var t1 = t - fi_up >> 31;
  31.   fi_up = (t1 & t) | (~t1 & fi_up);
  32.   if (ind < 0) {
  33.     var test = true;
  34.     for (var i = 0; i <= 9; i++) {
  35.       if (g[i] != f[i]) {
  36.         test = false;
  37.         break;
  38.       }
  39.     }
  40.     if (test) {
  41.       var old = document.getElementById('result').innerHTML;
  42.       document.getElementById('result').innerHTML = old + f.join() + '\n';
  43.     }
  44.     return;
  45.   } else {
  46.     var next = ind - 1;
  47.     for (var i = g[ind]; i <= fi_up; i++) {
  48.       f[ind] = i;
  49.       fsum_rem -= f[ind];
  50.       var a = Math.floor(f[ind] / 10);
  51.       var b = f[ind] % 10;
  52.       g[a] += (a == 0 ? 0 : 1);
  53.       g[b] += 1;
  54.       f_search(next, fsum_rem);
  55.       g[a] -= (a == 0 ? 0 : 1);
  56.       g[b] -= 1;
  57.       fsum_rem += f[ind];
  58.     }
  59.   }
  60. }
  61. function time_shot(id) {
  62.   var t_stamp = new Date();
  63.   document.getElementById(id).innerHTML = t_stamp.getHours() + ':' + t_stamp.getMinutes() + ':' + t_stamp.getSeconds() + ':' + t_stamp.getMilliseconds();
  64. }
  65. </script>
复制代码
分析:

频率为:
f0,f1,f2,f3,f4,f5,f6,f7,f8,f9
最大频率:
fmax = max(f0,f1,f2,f3,f4,f5,f6,f7,f8,f9)
频率总和:
fsum = f0+f1+f2+f3+f4+f5+f6+f7+f8+f9

假定 fmax 为 3 位数, 则 fsum <= 3 * 10 + 10 = 40, 而最小的 3 位数是 100, fsum > fmax >= 100, 所以无解;
假定 fmax 为 4 位数, 则 fsum <= 4 * 10 + 10 = 50, 而最小的 4 位数是 1000, fsum > fmax >= 1000, 所以无解;
...
fmax 的位数每增长 1 位, fsum 的上限只增长 +10, 而下限是以 10 倍增长, 所以断定 fmax 的位数不超过 2 位:
假定 fmax 为 2 位数, 则 fsum <= 2 * 10 + 10 = 30, 而最小的 2 位数是 10, fsum > fmax >= 10, 所以 fsum 属于 (10, 30];

任意一个频率 fi 有:
1 <= fi <= 30 - 9 = 21

所有 fi 中至多 2 个两位数

数字 i 在题面右侧 出现的总频率: (任意 i 题面左侧都已出现 1 次)
fi - 1
题面右侧 至少有 10 - (fi - 1) 行没有出现 i, 这些行右侧位置上频率数值总和至少是 10 - (fi - 1)
这些 i 对 fsum 的贡献至少为:
(fi - 1) * i

对数字 i , 其频率有上限:
(fi - 1) * i <= 30 - (10 - (fi - 1))
fi * i - i <= 20 + (fi - 1)
fi * i - i <= 19 + fi
fi * (i - 1) <= 19 + i
fi <= (19 + i) / (i - 1)

搜索算法以 f9,f8,f7,....f1,f0 的次序逐个设定,
在过程中, 所有尚未设定的 fi 的总和上限为:
fsum_rem
3

评分人数

TOP

本帖最后由 aa77dd@163.com 于 2015-6-12 07:21 编辑

回复 11# tigerpower

分析方法和解题思路可以完全和 十进制时一样, 只是问题在计算上的规模更大了, 如果没有更高效的算法, 耗时会指数规律增长

仍采用 8 楼的分析方法和求解算法, 耗时从 < 100ms 增长到 > 3 min
结果(注意数值是十六进制意义上的了)
1,11,2,1,1,1,1,1,1,1,1,1,1,1,1,1
1,D,3,2,1,1,1,1,1,1,1,1,1,2,1,1

感觉可以做一个猜想, 这两个解似乎都有一个通项公式:
以 R0, R1, R2, ... 表示各个数字出现的频率:

A. 进制基数 >= 3 时, 下面解成立:
1,(进制基数+1),2,1,1,1,1,1,1,1,1,1,1,1,1,1
R1 = 进制基数+1
R2 = 2
其他频率都为 1

B. 进制基数 >= 7 时, 下面解成立:
1,(进制基数-3),3,2,1,1,1,1,1,1,1,1,1,2,1,1
R1 = 进制基数-3
R2 = 3
R3 = 2
R(进制基数-3) = 2
其他频率都为 1

当然以上只是猜测而已, 对其他进制是否成立未作验证, 也无任何推理.
  1. <html>
  2. <body>
  3.   结果
  4.   <br>
  5.   <textarea id="result" style="height: 100px; width: 300px;"></textarea>
  6.   <br /> 运行时间从
  7.   <span id="start"></span>--
  8.   <span id="end"></span>
  9.   <br> cnt=
  10.   <span id="cnt"></span>
  11.   <br>
  12.   <button type="button" onclick="run();">运行</button>
  13. </body>
  14. </html>
  15. <script>
  16.   var g = new Array(0x10);
  17.   var R = new Array(0x10);
  18.   var H = new Array(0x10);
  19.   var cnt = 0;
  20.   function run() {
  21.     time_shot('start');
  22.     init();
  23.     f_search(0xF, 0x30);
  24.     time_shot('end');
  25.     document.getElementById('cnt').innerHTML = cnt;
  26.   }
  27.   function init() {
  28.     for ( var i = 0; i <= 0xF; i++) {
  29.       g[i] = 1;
  30.     }
  31.     cnt = 0;
  32.   }
  33.   function f_search(ind, fsum_rem) {
  34.     if (ind < 0) {
  35.       cnt++;
  36.       var test = true;
  37.       for ( var i = 0; i <= 0xF; i++) {
  38.         if (g[i] != R[i]) {
  39.           test = false;
  40.           break;
  41.         }
  42.       }
  43.       if (test) {
  44.         var old = document.getElementById('result').value;
  45.         for ( var i = 0; i <= 0xF; i++) {
  46.           H[i] = R[i].toString(16).toUpperCase();
  47.         }
  48.         document.getElementById('result').value = old + H.join() + '\n';
  49.       }
  50.       return;
  51.     } else {
  52.       var t = ind - 2 >> 31;
  53.       var fi_up = t & 0x21 | ~t
  54.           & Math.floor((0x1F + ind) / (t | (ind - 1)));
  55.       if (ind == 0 && fi_up > 3) {
  56.         fi_up = 3;
  57.       }
  58.       t = fsum_rem - ind;
  59.       var t1 = t - fi_up >> 31;
  60.       fi_up = (t1 & t) | (~t1 & fi_up);
  61.       for ( var i = g[ind]; i <= fi_up; i++) {
  62.         R[ind] = i;
  63.         var a = Math.floor(R[ind] / 0x10);
  64.         var b = R[ind] % 0x10;
  65.         var c = a == 0 ? 0 : 1;
  66.         g[a] += c;
  67.         g[b] += 1;
  68.         f_search(ind - 1, fsum_rem - R[ind]);
  69.         g[a] -= c;
  70.         g[b] -= 1;
  71.       }
  72.     }
  73.   }
  74.   function time_shot(id) {
  75.     var t_stamp = new Date();
  76.     document.getElementById(id).innerHTML = t_stamp.getHours() + ':'
  77.         + t_stamp.getMinutes() + ':' + t_stamp.getSeconds() + ':'
  78.         + t_stamp.getMilliseconds();
  79.   }
  80. </script>
复制代码
1

评分人数

TOP

回复 10# 523066680

觉得这个题目使用的数字应该以进制来限制, 比如 9 句话时用 9 进制, 只能出现 0 -- 8 这些数字

那么, 下面两个结果在 9 进制意义上应该是不成立的
1,9,1,1,1,1,1,1,1
1,11,1,1,1,1,1,1,1

TOP

本帖最后由 aa77dd@163.com 于 2015-6-12 20:42 编辑

回复 15# 523066680

这些算法能不能遍历?

我初步理解是一种趋近算法, 但不知道能不能保证 收敛, 尽管两个算法事实上都得到了了一个解.

趋近的算法不能 收敛 时, 一种可能会未能遍历问题所有可能待测状态而跳出, 还有一种可能是无限循环, 但不能遍历所有可能待测状态也不能得到存在的解.

TOP

返回列表