- 在线时间
- 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次,也就是说保留一个以外都得移动。
# L) D+ K- h: W$ K1 Y& M+ G- g3 g4 h& B8 q
另外发现一个简化公式 n - (n*n/x)。用这个公式计算的结果在一些情况有少量误差。
+ z& t0 U( K0 q/ i我也没有标准答案来判断误差,只是用随机模拟的方式,对指定的 n x 随机几百次试验确定最有可能的值,以下是代码,效率一般,但n在1000以上几百次模拟也能在几秒内搞定:7 ~4 F0 P4 O* n( k# u
( J# n! D5 L+ z/ o
( Q( K3 m, v% P0 N, F+ ~1 [C#code:
6 S# {: ]( U8 w& j8 ? s private void button1_Click(object sender, EventArgs e)& b9 y2 V1 x5 X l( g9 ^
{
: d! Y V! Z, d; B //新的描述:编号 1 -- X 的停车位,随机停放 n 辆车,无论当前车辆怎样的位置,最少让多少辆车重新停放
% a5 i3 C! E0 d5 ~7 u' x // 就可以使所有车辆连续停放
: I1 F* M; Q$ C* g$ u) W; U& x ( ]; l% u/ v7 y1 ?9 d. w
int n = int.Parse(textBox1.Text);3 N, H" V, n3 l" D- m2 d, b
int x = int.Parse(textBox2.Text);, C* Q0 x" \% j4 R
, k: W! ?: w* ~, V5 r
//500次随机模拟的最接近数字,对比公式计算* b1 q: L8 Z+ |8 ~! R8 _5 @2 r& ?
int maxValue = 0;( r" D6 c& c1 ], d% U8 }
for (int i = 0; i < 500; i++)
. ~) \2 b( L+ E1 P {
2 h5 ^# p. Z1 Z2 Y+ `- R int value = randResult(x, n);
" F: m8 x) D- z- j if (maxValue < value) maxValue = value;
; s( w. c3 J1 I lbMsg.Text = i.ToString();
, V. b& Z4 P8 Y* q X6 s lbMsg.Refresh();
6 k% H8 C o! X7 I }
0 A" S9 m6 M2 `+ `! i1 z textBox3.Text = maxValue.ToString();
: E' ]. Q' H9 Y; g
& M" h& d; l. N% L+ L/ B7 m$ _ //这是公式计算的结果,据观察大部分正确,少数误差也不超过 3 :)
7 ^, Y6 S$ M2 ~) l5 _+ U double newValue = (double)n - ((n*n)/(double)x);- m5 d' g7 c; O- e! F
textBox4.Text = newValue.ToString();
_$ e' p2 ^$ X+ G8 v7 y* L' d$ O }
z( N6 b7 K2 z6 M7 ]1 i. a+ z9 s. e& s
private int randResult(int max, int n)
7 I/ o- n7 h" X4 }5 s {
$ {/ U, D; a8 l ]/ l" K if(max <= n) return 0; //error, u4 ^) ?8 Q7 P. y
if (n < 3) return 0; //error" }! A6 J# F% B
if (max < 3) return 0; //error! \* x- f' y6 S2 L1 a+ R( H
7 E( q7 k4 e/ N( W6 F1 Z int[] lib = new int[max + 1];, d1 e7 l/ p2 g, V" G, y) O
//随机产生数字来填充* X" ]4 V J$ T# [& `7 m
lib[1] = 1; lib[max] = 1;
6 s( K c0 D& F0 S( l5 b int count = n - 2;
6 @# i5 V) K0 P% @" z Random rand = new Random();
1 s3 y! g6 b! g/ z while (count > 0)
; R4 j# Y4 ]& y6 ^2 P3 K% D% C {( e# a) D1 R- D, a' ~7 i6 I! w
int rnd = rand.Next(1, max);
; j3 E/ A; }/ v8 ]( `0 l4 k if (lib[rnd] == 0)
0 J0 u' h2 ?, h, J0 c {& x& r5 T `( [! U: L
lib[rnd] = 1;
/ R& D3 s4 a4 J6 f- y' l& L' K: S$ y count--;* n5 ^) p; C) f, b/ j
}5 r) c/ Q6 }9 y1 |. n
}
( x4 t' t4 ~2 F: U //循环检查最密集区域,也就是需要移动最少的区域
) S& { u$ H8 {5 }$ F8 t int min_space = n;
( l3 X/ u/ i& q9 k9 i7 i/ A for (int i = 1; i <= max - n + 1; i++)
/ N4 |2 E% b7 H8 I {" g- v5 ?$ r0 `. Q9 r& z- f
int space = space_count(lib, i, n);
# K! R& K' T8 z2 }6 X" D if (min_space > space) min_space = space; i9 p9 M0 h+ n( g' K
}
$ G. _) j) n' O# j7 p. G return min_space;9 Y) `* c* ^6 W$ A- _$ o: h7 C6 O5 A
}
5 s- Y( c3 K& u" v6 i
* R6 x1 z# g7 R7 | private int space_count(int[] lib, int start, int n)% }- J7 N: B' ]4 z6 k. p
{ //检查数组start后面n项数据里面有多少个14 a' d1 _# l8 p: |: m
int count = 0;8 C' ~, X, f" F
for (int i = start; i < start + n; i++) if (lib[i] == 0) count++;
# |+ ]9 D4 L0 \3 m* d return count;: b: h; o& I+ Y, x* v" `
}
1 L% ~& t* [! ^" _7 I" u |
|