- 在线时间
- 2 小时
- 最后登录
- 2017-8-7
- 注册时间
- 2010-6-27
- 听众数
- 2
- 收听数
- 0
- 能力
- 0 分
- 体力
- 40 点
- 威望
- 0 点
- 阅读权限
- 20
- 积分
- 14
- 相册
- 0
- 日志
- 0
- 记录
- 0
- 帖子
- 3
- 主题
- 1
- 精华
- 0
- 分享
- 0
- 好友
- 0
升级   9.47% 该用户从未签到
|
已经能够确定的是:如果 x > (n * (n-1) + 1),表示密度太‘稀’了,这种情况下必然是移动 n - 1次,也就是说保留一个以外都得移动。
! G; G3 s7 H- [* _+ j; R7 t0 R2 s, x( g2 n
另外发现一个简化公式 n - (n*n/x)。用这个公式计算的结果在一些情况有少量误差。7 a, Y; H) r4 L& C3 ]4 Q* o
我也没有标准答案来判断误差,只是用随机模拟的方式,对指定的 n x 随机几百次试验确定最有可能的值,以下是代码,效率一般,但n在1000以上几百次模拟也能在几秒内搞定:& V7 `0 t' L }9 S5 B/ }
2 } ^0 |+ p4 x/ {) Y W- \1 u0 l" `( r- h& }, _
C#code:: l6 o6 D1 M e- H! ^: l% g
private void button1_Click(object sender, EventArgs e)/ r ?8 R1 E5 B
{
0 H' C! w4 e1 O ^3 W) y //新的描述:编号 1 -- X 的停车位,随机停放 n 辆车,无论当前车辆怎样的位置,最少让多少辆车重新停放
* B# s& S' c! c2 ]5 J }. m // 就可以使所有车辆连续停放! S! i3 n$ q4 T1 O7 g+ c7 E
6 h: A& O' \& H; M4 c, T
int n = int.Parse(textBox1.Text);& c! E8 C) Z. i, Y) U% H' m5 f
int x = int.Parse(textBox2.Text);
/ l% l w" _3 e5 s. ] ^. `
/ k/ Y5 @* L+ P) a1 b //500次随机模拟的最接近数字,对比公式计算
I0 v6 j2 Z0 R% A int maxValue = 0;, S; Y) D: \! ]0 @, _
for (int i = 0; i < 500; i++)
; f9 A$ w, l) g9 n# H' F3 b2 \ {- z O% ?- Y/ {4 Q% R( v
int value = randResult(x, n);
9 v3 p1 w# ^* R% z3 l4 x3 J3 c if (maxValue < value) maxValue = value;6 Q- `$ |3 b; R% ]$ D. N
lbMsg.Text = i.ToString();3 l9 P! a$ k) q2 L" s7 V
lbMsg.Refresh();
+ M8 T# p. V1 D. _; f( } }
# j' \5 X8 e/ ` textBox3.Text = maxValue.ToString();! C- r4 ]* S0 J$ X4 r4 O: I8 Q
. @4 t: I D0 I- N
//这是公式计算的结果,据观察大部分正确,少数误差也不超过 3 :)
; s R$ Q/ S% y7 h h: A double newValue = (double)n - ((n*n)/(double)x);; x9 X) |9 }) q4 d1 Z* @
textBox4.Text = newValue.ToString();
# W* w4 D s. H# a% i }
8 j! W/ B {; G6 G
0 |1 ~5 F# t; |6 g private int randResult(int max, int n). t% I/ j1 J) y; L- y
{9 s. t( [4 C9 i, h( r' T
if(max <= n) return 0; //error
: Q/ }( e! z; \+ P$ S9 g if (n < 3) return 0; //error5 o( ?% W d; Y5 P; h1 U, u
if (max < 3) return 0; //error. H- `+ N( @ y
4 C9 p) d2 h- @0 R; t* j int[] lib = new int[max + 1];' u. X0 m1 z3 C2 I" F+ l
//随机产生数字来填充# J/ W5 v& B- p1 ^4 K7 n$ E" }, W$ [
lib[1] = 1; lib[max] = 1;# ^1 ^* E3 O/ s0 I( f: Q
int count = n - 2;
: b& J* i# X. Z, O. z( y Random rand = new Random();& E1 w8 ~$ G( F
while (count > 0)
, g% m% E8 T- |/ } T& w1 Z. R {( Z- i- P! {5 h+ G' e4 M% ]
int rnd = rand.Next(1, max); u. y3 I. M2 X- ^0 H" K
if (lib[rnd] == 0), T: }& p/ a0 {
{9 s6 Z4 _% O( k% y0 e
lib[rnd] = 1;4 `% U5 Q i, n% G2 d V: K9 X# q
count--;9 P: ]1 b! H# p" R" q3 p
}
$ S& y- i3 V9 Z/ t8 a* q7 X. Y }9 H6 g. U0 i' X7 w
//循环检查最密集区域,也就是需要移动最少的区域
/ Y. M! a k. e$ ~ int min_space = n;; A0 s/ Z3 _, a4 \' G$ U& K% l: w
for (int i = 1; i <= max - n + 1; i++)
; W6 O4 ?) ?" u. |9 b- Y. q {
$ v! @# g+ v0 ~2 l5 `: q7 P int space = space_count(lib, i, n);
; M% f7 [" U1 B' u1 D6 N% q if (min_space > space) min_space = space;" f; b+ S3 D }5 m }
}8 u8 n( m/ i8 {
return min_space;
& Z# J$ J( g1 l) _7 ?$ m }3 l4 X0 Q0 i! z" e. K* c" g! r: r
, p; @. r; p% ^7 E
private int space_count(int[] lib, int start, int n)
/ n0 G; P+ K$ x4 X4 F# [ { //检查数组start后面n项数据里面有多少个1. r0 c( S8 N- o' \. V. o4 a
int count = 0;6 T% ^0 h% e" g
for (int i = start; i < start + n; i++) if (lib[i] == 0) count++;& p& Q* ?- z5 v' q; ?
return count;1 S& A, L. [9 r7 J0 ]. ?
}
7 k( ^- N, h. V6 R |
|