- 在线时间
- 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次,也就是说保留一个以外都得移动。4 M& W B- j- S/ j
4 G7 d/ v# X% |+ p" |
另外发现一个简化公式 n - (n*n/x)。用这个公式计算的结果在一些情况有少量误差。: Q( H) m" ~. u3 R* w$ m E
我也没有标准答案来判断误差,只是用随机模拟的方式,对指定的 n x 随机几百次试验确定最有可能的值,以下是代码,效率一般,但n在1000以上几百次模拟也能在几秒内搞定:# \1 v& h0 J' H# r: p( @9 T8 c
, i; f! d: {" b6 J7 |( L2 p% C
- U& G, Z' w8 ^6 ]+ W* U, {
C#code:2 g. e x/ D4 z! z" ?/ J
private void button1_Click(object sender, EventArgs e)! k# G9 _: r5 z* ~1 g' h
{
1 g0 w0 I$ G2 x+ S$ S+ B7 W //新的描述:编号 1 -- X 的停车位,随机停放 n 辆车,无论当前车辆怎样的位置,最少让多少辆车重新停放0 [$ q. V9 L/ w: M8 U
// 就可以使所有车辆连续停放
2 K) g8 D) m% j& D* M3 `8 Z
* Z& }4 d! Q' h" H0 \) B6 i! Z int n = int.Parse(textBox1.Text);
. p% T9 Q! V, J# V3 Q \' Q* B int x = int.Parse(textBox2.Text);- Z3 R" ~4 @* x
/ F$ h4 f, `2 _9 g, K6 G0 i //500次随机模拟的最接近数字,对比公式计算
/ ^8 X8 q: c! Y! Z int maxValue = 0;$ P! R+ H4 v D" G6 O9 H
for (int i = 0; i < 500; i++)1 D5 i* D# L3 x: i) V2 k% h
{- G% K- Z- B& i
int value = randResult(x, n);
9 Z. B+ l `. p0 n if (maxValue < value) maxValue = value;/ M+ i. n& X" i0 R/ r2 P6 `' `
lbMsg.Text = i.ToString();
6 i7 |; G7 f, N# }1 r1 o1 g lbMsg.Refresh();4 i( ^1 U! {+ q) |/ ]
}" x9 X3 f% {1 R: I3 Z2 P4 D
textBox3.Text = maxValue.ToString(); J; M& _! I1 V5 o' N. \1 c
- z6 l( h5 G' @. A6 X' C7 W! t7 G //这是公式计算的结果,据观察大部分正确,少数误差也不超过 3 :)
" f7 v+ t3 i- v7 I* Y# J, A double newValue = (double)n - ((n*n)/(double)x);
# I) k7 r* I9 Z' z7 M2 p4 Z textBox4.Text = newValue.ToString();
X7 o) u- g/ a4 Y. t5 g' y }
1 g, r% `5 X5 m; i4 p
0 n6 I( P9 N3 {0 K: w private int randResult(int max, int n). G( k% g- o2 v+ x6 L3 w; m) u, t
{
. b, t$ N( J# c4 P* x0 d if(max <= n) return 0; //error
( v: e" l7 s' [( y# S. z. ` if (n < 3) return 0; //error
9 \- z; z/ [) g# r if (max < 3) return 0; //error* ^4 W. ]" {4 w" x" ]2 E* o
) D/ X) I6 [! t& E( F, T6 w8 m
int[] lib = new int[max + 1];
* `' t7 g: y" c1 c; K //随机产生数字来填充
1 C- v; w( p1 a8 t, l lib[1] = 1; lib[max] = 1;
0 U2 U% j5 C) p" N! @6 o+ g int count = n - 2;
4 v) G" T! ~* w/ V5 y Random rand = new Random();% V/ i2 v5 y g8 ^* U( R' @ m0 R
while (count > 0)
' I. x9 t v- s0 v* t6 I& D {
& S5 D6 p! K: k$ M int rnd = rand.Next(1, max);5 d) R. b k2 N2 `1 C5 b) w- g
if (lib[rnd] == 0)2 j& G n$ E2 {/ u! p8 U- K0 z
{+ r+ R9 c9 W/ j& K6 @8 |
lib[rnd] = 1;% {5 E& }4 i4 Q2 m
count--;
( M6 b0 N9 @& s5 O6 p }
- a+ M9 N% b, E! x5 p4 ]; U2 a }
/ A. n# d) E% ` //循环检查最密集区域,也就是需要移动最少的区域* j- R) Y5 H3 M) D" f( h) }$ E" z6 b
int min_space = n;' p+ D- h) e+ R0 z7 l; K
for (int i = 1; i <= max - n + 1; i++)5 ?2 a0 z" x- {& Z5 y) ~, j
{% c; ]1 w5 I @
int space = space_count(lib, i, n);
& u2 t+ o0 v1 A: F! F8 y( u if (min_space > space) min_space = space;
; U3 @% m+ |% ` }4 C6 L, E) y! e0 u& M
return min_space;
: F$ x: z' @. `; d7 d$ f7 n }
: j# C- ]# E# y6 ^. T) }' g8 I* _/ ]- w7 z, W( E
private int space_count(int[] lib, int start, int n)0 r R4 f# M0 D' ^; B
{ //检查数组start后面n项数据里面有多少个1( U4 U) p/ x0 \) ?
int count = 0;
8 v; O4 A( `6 z- Y. q. W8 h" O for (int i = start; i < start + n; i++) if (lib[i] == 0) count++;. `5 _0 P0 H: a2 P2 k+ R/ i% M
return count;# v5 [* s! k& e, E6 x
}
, T, [# }/ M' V |
|