- 在线时间
- 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次,也就是说保留一个以外都得移动。
" [& k8 M* k% {7 G: J$ N% \7 V A5 {$ `& k! H' j
另外发现一个简化公式 n - (n*n/x)。用这个公式计算的结果在一些情况有少量误差。
5 L% v# ]2 G/ @3 e' i' L9 h我也没有标准答案来判断误差,只是用随机模拟的方式,对指定的 n x 随机几百次试验确定最有可能的值,以下是代码,效率一般,但n在1000以上几百次模拟也能在几秒内搞定:
/ h4 V6 k+ P, [0 F8 R2 B5 V/ w. v
( C1 o1 ~* w# M+ H7 b2 J2 I- }/ P0 \
C#code:0 ~) \- V1 L+ @3 s
private void button1_Click(object sender, EventArgs e)
: o% o5 O6 d8 i8 i4 x {
3 l4 u( L) H+ [- {, ` //新的描述:编号 1 -- X 的停车位,随机停放 n 辆车,无论当前车辆怎样的位置,最少让多少辆车重新停放9 a( F6 v- e$ Q, b
// 就可以使所有车辆连续停放
" Q' w" y: _- g' T K# E, F 2 E* L4 h d7 a3 ^+ X8 E/ h
int n = int.Parse(textBox1.Text);
# o: B% R: x& { J# U7 h int x = int.Parse(textBox2.Text);7 H9 o( a: R+ g, ]6 p* B9 a
4 B# t. V% |, W N; i //500次随机模拟的最接近数字,对比公式计算
( Q) [: x+ s7 J( Q# Q% { Z2 ^. V$ W/ r7 c int maxValue = 0;
, f4 I$ p! `/ @8 g& v$ A% l for (int i = 0; i < 500; i++)
1 j) v6 f4 I8 K4 [9 { {
7 ~$ }& c- m6 N1 D! \- S, V8 L( A2 M int value = randResult(x, n);
9 V' ]3 ~% z- L" [- e9 }! D, n; K if (maxValue < value) maxValue = value;
8 z% ~# \. V3 _5 X4 B+ b lbMsg.Text = i.ToString();' i% ~# E. ~* A% J- _( m
lbMsg.Refresh();: n# x, C( f% L, f* D* F
}2 N% h$ H X8 i: M' a
textBox3.Text = maxValue.ToString();1 Y" q; E( W! Z, |6 ^7 j" B, O
+ ^1 J% S& C- Z1 c3 T //这是公式计算的结果,据观察大部分正确,少数误差也不超过 3 :)) v; m7 U# d' y1 c' M r
double newValue = (double)n - ((n*n)/(double)x);
" r" ]: s u; D7 Q textBox4.Text = newValue.ToString();) @+ W! V0 I4 s5 Q0 O" n Q
}
: I. n, C6 k* M5 l/ g; \' G+ S% X1 I5 ]% `
private int randResult(int max, int n)& c6 @- V& k% K7 h+ ~* X
{
8 v" h, o. n# F) Y if(max <= n) return 0; //error
1 o( A2 F: j9 i! J! t1 ^& j3 T if (n < 3) return 0; //error
2 Y0 ^& i3 F3 ?) f5 C: x if (max < 3) return 0; //error% w) x& |: A# i9 t% z! O
4 f1 ~5 r7 J2 O; ]
int[] lib = new int[max + 1];
; J5 Z( H1 G: I6 U$ Y2 _3 u. w1 r# | //随机产生数字来填充% p, r/ V- S) I/ k, Y! L- O
lib[1] = 1; lib[max] = 1;* b0 F+ S- L* X, q" a5 c, s* f
int count = n - 2;8 p( t' |+ [6 ^7 z, W, I" M7 \
Random rand = new Random();: f1 Z. `! v- `+ H
while (count > 0)
! u6 d$ d9 _5 Z3 w/ |1 p# E7 s {
( |( E5 v4 ^6 Q r5 p9 L% w int rnd = rand.Next(1, max);+ Q# X' \! l' }5 T* g5 X7 K6 h
if (lib[rnd] == 0)
. a& m' S4 Z0 F3 M {
3 i) c8 d& U: e, {- \ lib[rnd] = 1;
; V6 V# |- c: b( k& t count--;! j2 z& p* Q5 n! y
}0 j' Q9 g4 R$ C6 X: }, q- C
}
8 h% Q4 I: @9 U$ V( t //循环检查最密集区域,也就是需要移动最少的区域
- N7 {$ H6 L s! X( @! _5 _0 G int min_space = n;
8 J) ~" t. F0 C1 ^& k for (int i = 1; i <= max - n + 1; i++)/ ?6 _0 M `3 }; \3 S
{/ Y% H" ]% Y# f1 a- ^1 l+ C
int space = space_count(lib, i, n);7 q. _( Z# w; c e8 g
if (min_space > space) min_space = space;6 v- S( K; e, r# C, Q3 Y* l. R8 K
}* P& b7 L: [( F: `9 @3 H
return min_space;1 q+ {* ?+ X' y" K
}
% q1 f- r0 v# C' {# S1 k2 b
5 s7 V+ I2 V, ~( U6 } H private int space_count(int[] lib, int start, int n)
8 x: y. B: S1 N! X5 d { //检查数组start后面n项数据里面有多少个1
& m* ?0 S5 v: ?" C. S% ~ int count = 0;
5 {* [3 Z- a/ w* d for (int i = start; i < start + n; i++) if (lib[i] == 0) count++;4 q0 Q& t8 x q$ {1 M- y
return count;
& f7 U4 C% d# b) u }4 K+ {. W5 z' q' W( z O5 C( A
|
|