菜鸟问题第3号

puning 2001-09-10 08:04:13
有数列a[1..6]
3 2 1 7 6 5
可推出数列b[1..6]
0 0 0 3 3 3
b[i]==从a[i]到a[1]比a[i]下的数的个数.

1.怎样由A->B(白痴都会)
2.怎样由B->A(我的算法已有初步模型)
想请教各位高手!
...全文
113 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
puning 2001-09-12
  • 打赏
  • 举报
回复
我的算法比较类似动态规划
例 B-> 0,0,0,3,3,3
1:0
2:0 1
3:0 1 2
4:(0+1) (1+1) (2+1) 0
5:(0+1+1) (1+1+1) (2+1+1) 0 1
6:(0+1+1+1) (1+1+1+1) (2+1+1+1) 0 1 2
即 3 4 5 0 1 2
再用6减 (6-3) (6-4) (6-5) (6-0) (6-1) (6-2)
解为3 2 1 6 5 4

dongmen 2001-09-11
  • 打赏
  • 举报
回复
。。看起来很复杂
starfish 2001-09-11
  • 打赏
  • 举报
回复
上面的代码其实很简单的
这个问题是我初学编程时候就遇到的问题(阶乘进制),其实很简单。
阶乘进制在IOI97(好像是IOI97)的一道魔方类型的题目中用到,用来压缩存储状态。
starfish 2001-09-10
  • 打赏
  • 举报
回复
这个问题和一种计数法相联系,叫做“阶乘进制”。阶乘进制经常用来生成全排列,他可以用一个0~n!-1的整数表示一个1~n的全排列;经常在搜索中利用这种方法压缩数据,比如常见的一种8数码问题,他的一个状态可以用1~9的全排列来表示,如果按照一般的存储方式至少需要9个整数字长,但使用这种阶乘进制来压缩至需要一个整数就可以表示一个状态。

先说明一下阶乘进制的原理

因为
n! = n*(n-1)! = (n-1)*(n-1)! + (n-1)!
= (n-1)*(n-1)! + (n-2)*(n-2)! + (n-2)!
= (n-1)*(n-1)! + (n-2)*(n-2)! + ... + 2*2! + 1*1! + 1
所以
n! - 1 = (n-1)*(n-1)! + (n-2)*(n-2)! + ... + 2*2! + 1*1!
这就是说,0~n!-1中的任何一个整数可以表示为:
a[n-1]*(n-1)! + a[n-2]*(n-2)! + .. + a[2]*2! + a[1]*1!
这里 0 <= a[n-1] <= n-1, 0 <= a[n-2] <= n-2; ... 0 <= a[2] <= 2; 0<= a[1] <= 1
这样 0 ~ n!-1的任何一个整数都可以展开成为 (a[n-1], a[n-2], ... , a[2], a[1])
由于 0 <= ai <= i,因此可以理解成1~n个数的排列中,数 i+1 右边比它小的数的个数。因为比i+1小的数最多有i个。例如对于1~4的全排列而言,共有4! = 24种,
4!-1 = 3*3! + 2*2! + 1*1! = 23,
对于0~23的任何一个数,比如19,可以写作:
19 = 3*6 + 1 = 3*3! + 0*2! + 1*1!
这表示19对应于(3,0,1),其中
a[3] = 3 表示排列中4的右边有3个数比它小;
a[2] = 0 表示排列中3的右边没有比它小的数;
a[1] = 1 表示排列中2的右边有1个数比它小;
这个排列就是 4213


根据阶乘进制生成排列的算法描述如下:


假设已经得到 A[1..n-1](这一步很简单),其中A[i]就是阶乘进制中的系数,并且表示在最终生成的排列中数字i+1的右边有A[i]个数字小于i+1;

var
P: array [1..n] of integer; { 存放生成的排列 }
mark: array [1..n] of 0..1; { mark[i] = 1 表示 P[i]中已经放置了元素 }
A: array [1..n-1] of integer;{ 存放阶乘进制的系数 }

....

for i:=1 to n do mark[j] := 0; { 初始化 }

{ 注意体会这里downto的意义,因为从大到小确定数字,
要使i+1的右边有a[i]个小于他的数字,
只要使i+1的右边有a[i]个空格即可 }
for i:=n-1 downto 1 do
begin
j := n; m := 0;
repeat
if mark[j] = 0 then m := m + 1; { 记录空格数目 }
j := j - 1;
until m = a[i] + 1; { 一直找出a[i]+1个空格为止,最后一个空格用来放置i+1 }
j := j + 1; { j 多减了一次,现在加上 }

P[j] := i + 1;
mark[j] := 1;
end;

{ 下面找到数字1所放置的位置 }
j := 1;
while mark[j] = 1 do j := j + 1;
P[j] := 1;

for i:=1 to n do write(P[i]);
writeln;
....

dongmen 2001-09-10
  • 打赏
  • 举报
回复
cry
我也是菜鸟
CNer 2001-09-10
  • 打赏
  • 举报
回复
不是一般的才鸟哦。。。
starfish 2001-09-10
  • 打赏
  • 举报
回复
想到了:)等一下我写出来
starfish 2001-09-10
  • 打赏
  • 举报
回复
有的有的,我做过的,等会儿我想想
dongmen 2001-09-10
  • 打赏
  • 举报
回复
这道题是。。95年分区联赛
我用深度搜索了,shrug,有更好的吗?

33,028

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧