- 在线时间
- 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次,也就是说保留一个以外都得移动。
2 z4 v* X2 w y+ A/ g
8 H! }: l) z0 q. k6 B另外发现一个简化公式 n - (n*n/x)。用这个公式计算的结果在一些情况有少量误差。$ A; C) z! c0 L
我也没有标准答案来判断误差,只是用随机模拟的方式,对指定的 n x 随机几百次试验确定最有可能的值,以下是代码,效率一般,但n在1000以上几百次模拟也能在几秒内搞定:
6 ]! W2 d( N7 z& N) ]& A
/ @% A9 Q% d |+ B9 d( }
3 ?4 y( O* F; F+ U, nC#code:+ c; x# P7 x7 ?" G
private void button1_Click(object sender, EventArgs e)7 I9 i* E' ^) |7 _/ v9 ?' k
{- x! _) }1 R% C
//新的描述:编号 1 -- X 的停车位,随机停放 n 辆车,无论当前车辆怎样的位置,最少让多少辆车重新停放" m9 k4 `, C& f2 v7 Y8 M
// 就可以使所有车辆连续停放
4 p0 P2 ]0 |! i$ Z. \ & z5 _9 A5 p ~& C8 T1 n8 z) B
int n = int.Parse(textBox1.Text);5 [8 } [& Z! }3 k2 @' W
int x = int.Parse(textBox2.Text);2 a8 l5 N& m2 Z: s7 t$ @4 I: a
: b: W* l; }/ W2 F- V
//500次随机模拟的最接近数字,对比公式计算3 ]" P: c$ n& w% R! F
int maxValue = 0;6 `; ]% o) u+ M- K; X. @, l/ d0 g
for (int i = 0; i < 500; i++)
4 \! B: a9 b* }- D) a {
( z% e1 V/ S4 ?8 A int value = randResult(x, n);3 h9 n0 {5 i& P" j1 @# p
if (maxValue < value) maxValue = value;! j, s& I4 G( m1 `7 _
lbMsg.Text = i.ToString();# h; M! f4 V+ Z+ J: w2 B
lbMsg.Refresh();
% {- ]5 I% {, _- x }
0 D v* `5 _9 z* @/ r/ T textBox3.Text = maxValue.ToString();
; L# T8 f8 C3 b* T' J1 l; T5 X6 r$ I& R O( {" {
//这是公式计算的结果,据观察大部分正确,少数误差也不超过 3 :)
]( G( }2 [2 h8 w double newValue = (double)n - ((n*n)/(double)x);1 E' u" n& k3 B; j3 p9 x( M0 \
textBox4.Text = newValue.ToString();
: p/ S. P& I% q }0 `% U6 j& F1 W7 d+ F4 _9 J# ], _+ K
" _, V: x. }4 R! D) o. i
private int randResult(int max, int n)5 ]9 D$ O1 j! N/ V% Q+ o
{
* H' {5 S, I" F! w if(max <= n) return 0; //error* _( o1 p% J, y% v
if (n < 3) return 0; //error
% g! D Y! B2 m1 Q if (max < 3) return 0; //error& {9 w' H! {: u, `8 _. Y
5 [6 _1 E3 A* a" F! x
int[] lib = new int[max + 1];" g1 @5 A: @1 y
//随机产生数字来填充
$ H7 z2 Z9 C9 k/ S" v lib[1] = 1; lib[max] = 1;
t# ~6 K4 w& T: m4 x int count = n - 2;
2 u, Q- W8 F& T/ [$ R; I Random rand = new Random();, |! h$ s/ A2 j) i, I
while (count > 0)
1 _- V- M, \9 G) [ {
" }1 s5 y( P/ W8 | int rnd = rand.Next(1, max);
8 b1 k/ ~& Q# a7 f! `5 G" i if (lib[rnd] == 0)' L6 C1 M. F$ g6 Q4 ~& A; w, e- }4 |7 q
{1 N: g; r5 q3 v: e
lib[rnd] = 1;& u) m6 [7 D4 Q+ L3 t3 s" p
count--;/ Z6 d0 F, Q4 A$ s( I9 Q1 Y" g, M
}
) C- m0 e# a* D' S+ m/ W* H }
6 p8 |9 R. s# f6 w, O5 c& L! @* T //循环检查最密集区域,也就是需要移动最少的区域
" K7 w: ?6 o; j, j/ z* }6 p int min_space = n;
9 |# }) P0 h8 m3 L for (int i = 1; i <= max - n + 1; i++)$ J6 k. [$ W# K5 B, T
{
) I. q- P8 r& N# c6 T8 c int space = space_count(lib, i, n);
& t q/ R( {! I3 q if (min_space > space) min_space = space; K" n( Y, I, N% z/ Z) d4 r6 m
}
' Y U/ N0 Y4 |( n7 b8 m return min_space;: q8 Q! A9 Y# V" }- K7 F ]
}
9 R3 S6 i+ f9 q$ {1 ]
( g0 l- z0 v8 [ private int space_count(int[] lib, int start, int n)0 }. {% n, V/ b# |
{ //检查数组start后面n项数据里面有多少个1
: J. g* g$ l" ?2 s6 t int count = 0;% O, m8 X% r! R' X% \
for (int i = start; i < start + n; i++) if (lib[i] == 0) count++;2 \6 A% V, _9 Q! Z$ F5 }, i( }+ a; P* S
return count;2 X& `" D. r8 G' ]
} `. _% v4 G; l( k2 T
|
|