- 在线时间
- 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次,也就是说保留一个以外都得移动。
0 f4 A- k+ {. ]% q* W, z8 l
8 b% H5 W' x- D) k: \0 R另外发现一个简化公式 n - (n*n/x)。用这个公式计算的结果在一些情况有少量误差。
2 J3 P8 C. J+ f$ l1 @$ o我也没有标准答案来判断误差,只是用随机模拟的方式,对指定的 n x 随机几百次试验确定最有可能的值,以下是代码,效率一般,但n在1000以上几百次模拟也能在几秒内搞定:/ D9 W1 q% u t
) v1 [5 S6 W/ e0 W0 P& X/ X' C& }1 O
5 D6 T- E5 @- t9 ^$ W1 |( {% xC#code:, R @5 O6 V; S9 t# O
private void button1_Click(object sender, EventArgs e)
( o9 g+ _, t/ k; G' V$ a {/ w9 R6 e) l" a# O; ^3 Z5 x) Q
//新的描述:编号 1 -- X 的停车位,随机停放 n 辆车,无论当前车辆怎样的位置,最少让多少辆车重新停放) J- o7 `( E" n" |8 J
// 就可以使所有车辆连续停放: }: r9 F( e, g, w8 \& d" J! A
; p" z: K$ T4 G c( N& ?- X; k+ H
int n = int.Parse(textBox1.Text);
7 k8 y0 f, b; [% e4 X9 G int x = int.Parse(textBox2.Text);, t% H/ G$ [# F5 D
' j& h( A% Y% n8 v0 A- u //500次随机模拟的最接近数字,对比公式计算
9 O6 t$ Z8 Z7 D8 L/ W( g int maxValue = 0;
( }5 y" ?7 k( l for (int i = 0; i < 500; i++)1 d# i( G; y4 ]# B2 B* Y+ t8 V$ z
{ D$ X- t1 d" P) T
int value = randResult(x, n);8 Z6 f% p, d% j& i6 N0 t# Z8 e
if (maxValue < value) maxValue = value;. E2 }, R% w! s; g% K9 j
lbMsg.Text = i.ToString();
9 M. Z2 |! O; [+ a& w' U/ j lbMsg.Refresh();: L4 i! R7 f' p6 {2 Q
}
4 a( I* k7 W& N textBox3.Text = maxValue.ToString();5 h$ z- @( g: _0 i6 R
: Z9 Z& p7 |; k3 v# W+ y8 {( r- b) P8 Y
//这是公式计算的结果,据观察大部分正确,少数误差也不超过 3 :)
2 o5 |% i+ y- a( x double newValue = (double)n - ((n*n)/(double)x);) Z4 [5 k& Q) f+ b4 ?! p
textBox4.Text = newValue.ToString();- w" t( c% g9 A- R
}' Q% j- P8 l$ _
* j o" l5 W/ E! P# Y; r private int randResult(int max, int n)
q4 N P1 r- ^ {
# h9 o4 @3 u! Z7 u% } if(max <= n) return 0; //error5 D8 I& c6 W# x3 R( C1 ^
if (n < 3) return 0; //error
5 F) ^ y8 M) S6 | if (max < 3) return 0; //error* |# W, j' N2 {
; x8 J! R; E# H2 @1 Y: Q, e int[] lib = new int[max + 1];( d4 X0 h$ Z7 j' G; O: e/ u% M
//随机产生数字来填充
8 \( s& s2 Q0 d/ ~9 N) z3 v6 D6 u lib[1] = 1; lib[max] = 1;
" n' G; P1 y3 D3 C int count = n - 2;/ o1 \0 n; @# C8 ?) m. o/ s
Random rand = new Random();
6 o1 G0 l" ^( ^3 I- { while (count > 0)* |; K1 X+ x& v& j/ G' e
{- @. Z; s7 w& {
int rnd = rand.Next(1, max);$ |" s/ e* R; u0 {- b
if (lib[rnd] == 0), n- A4 S7 S; A D2 ?: k3 A) Y
{
1 o( v9 e" Q) O; S. ~0 {+ [% V lib[rnd] = 1;! X5 }1 r9 n" A
count--;
6 |* D2 l( I% W0 C! _ }" K8 v# C- I$ ]3 i4 r3 W( H& b
} F% ?" E; H( ]4 D9 i
//循环检查最密集区域,也就是需要移动最少的区域
{+ o9 U+ r( y. b [ int min_space = n;- {! R% H$ p0 N
for (int i = 1; i <= max - n + 1; i++)
5 y) y) a+ C7 D {9 m' M+ r3 H4 ?9 r1 ^. N
int space = space_count(lib, i, n);
' o& u7 k' b2 N+ B+ Y if (min_space > space) min_space = space;
6 t+ F. ^$ C: U }
) w+ S, B& |8 c2 t return min_space;
4 O) H) ^. g: j }& I% x: Q+ ], {5 J
: a7 T4 ~3 r! Z2 }- D z/ n private int space_count(int[] lib, int start, int n)
0 u* {) ^8 M# z! h; p* e) x$ m7 [ { //检查数组start后面n项数据里面有多少个1
( }% c( C4 W: n, S6 ~ int count = 0;
3 S+ G5 w* m, F4 c: ^# x" s for (int i = start; i < start + n; i++) if (lib[i] == 0) count++;
) u6 ^! _9 t: y0 B, z- v return count;
8 _. j" j9 F# A. w9 h$ ~: S }
- b4 W# O$ ?; q% K3 v |
|