- 在线时间
- 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次,也就是说保留一个以外都得移动。
3 w8 j+ Q$ g/ D y7 g. p( W- A( O! U# N4 e; P
另外发现一个简化公式 n - (n*n/x)。用这个公式计算的结果在一些情况有少量误差。9 H% E( ~' V3 }9 o
我也没有标准答案来判断误差,只是用随机模拟的方式,对指定的 n x 随机几百次试验确定最有可能的值,以下是代码,效率一般,但n在1000以上几百次模拟也能在几秒内搞定:) b: |. {* U, p
% L) e& U9 w/ l+ [0 f
; N3 g; M( S' M( W% S0 P H- K5 W3 c
C#code:
$ A4 v* f! i, r5 n6 M. f1 `1 v private void button1_Click(object sender, EventArgs e)1 _# [2 [% t; k6 v* {! |
{
% {* W, K( y& y) B4 M2 U //新的描述:编号 1 -- X 的停车位,随机停放 n 辆车,无论当前车辆怎样的位置,最少让多少辆车重新停放' q% T1 H; I" T- d& c* k
// 就可以使所有车辆连续停放' G/ k" c4 D1 d$ B' r
3 P# h% N/ I" B1 c$ U7 c' e
int n = int.Parse(textBox1.Text);4 i# O9 N3 o8 b0 W
int x = int.Parse(textBox2.Text);
0 ^7 g T- W5 h* p4 y
! r( A$ I; b c$ e% A A$ a //500次随机模拟的最接近数字,对比公式计算
5 h% ?( M% o5 A3 J k i2 x/ O int maxValue = 0;
3 t! X5 o% E2 G$ u3 L- Q2 Q4 | for (int i = 0; i < 500; i++)/ N2 C/ |6 q# z4 w @. g( d
{
: x! u6 Y" I* f W& ?$ f int value = randResult(x, n);! s- n; l# R. h) t8 j2 t
if (maxValue < value) maxValue = value;# N( @, k0 H: K: }+ y. M7 O- x/ [
lbMsg.Text = i.ToString();4 p, u2 u4 r# F8 K" q( i8 g0 m
lbMsg.Refresh();) N( N* b( g. C& n1 P& ^
}+ q0 ~3 W( Y5 `
textBox3.Text = maxValue.ToString();: y3 D0 I" b* P/ X D7 w$ Q: z
$ F' K& ]; p' o) n: d //这是公式计算的结果,据观察大部分正确,少数误差也不超过 3 :)
6 q5 L2 o8 j6 a" J0 w& p8 i( {& h/ D double newValue = (double)n - ((n*n)/(double)x);
+ n& W2 P$ V: e! z, W( a4 O! I textBox4.Text = newValue.ToString();4 f) G6 Q( I" O9 d0 [) D9 N
}
7 r1 s8 M1 u0 O+ m# W$ b5 n
7 p$ ^) H% M0 [ private int randResult(int max, int n)
0 b0 ?8 i$ M- S [ {# V y3 s H0 P2 c
if(max <= n) return 0; //error
4 ^- `( G+ ?& j+ ` if (n < 3) return 0; //error; `) e2 E2 }; w' Y/ M: {. P
if (max < 3) return 0; //error
4 {6 x, ^+ Y4 L! j+ Z: H7 d1 P' B$ _. k# [# Z2 @ y8 t
int[] lib = new int[max + 1];2 V0 D/ T3 d- l5 e% n. g1 ` Q& g
//随机产生数字来填充- M( }" i8 G5 ~* P8 ]
lib[1] = 1; lib[max] = 1;
; t2 W! T; z5 p% } int count = n - 2;# |4 Z0 o# D' j8 ?+ u r7 L; G2 |6 o
Random rand = new Random();
" S, u- K! V' B# Y. r while (count > 0)
5 b% l# y$ U/ |& {5 ^. X# H& o3 K { [" Q1 k8 h. T: e9 Q; C6 F! B
int rnd = rand.Next(1, max);2 X, D% }( ?8 E: C5 w% X9 `
if (lib[rnd] == 0)
% V! H% O4 T$ G2 Z* H {" V0 P- D/ R. w4 b+ j* }' W
lib[rnd] = 1;
; f. T R+ }3 m8 s count--;& k4 Y, k: j7 u7 f+ r
}
9 P& s1 }+ a% s: ~" @ }) s5 V5 O5 M+ {' a0 x4 T
//循环检查最密集区域,也就是需要移动最少的区域 o' K/ d6 V6 o
int min_space = n;5 b. p. F# G7 n
for (int i = 1; i <= max - n + 1; i++)# z! V: W, I6 I# m+ g5 }
{3 f P0 l; |4 o4 V" d- L
int space = space_count(lib, i, n);0 R) L! l6 S! u& F" }1 B
if (min_space > space) min_space = space;
" y& ]: A! O1 N6 d5 A% u }
+ ~) f3 G" b! U4 D- T return min_space;8 U$ s% y# o8 v; ~6 D) H0 w
}
2 V& y4 J: W [, v) c; H
. X8 B+ R: \1 Q( r( S( n! { private int space_count(int[] lib, int start, int n)
& K6 x$ Z- D% Z* \! J2 k5 @' Q! k { //检查数组start后面n项数据里面有多少个1# ]0 n( u4 z- m ?9 e) b: W
int count = 0;* J' K2 g' p+ E# m. _
for (int i = start; i < start + n; i++) if (lib[i] == 0) count++;
) p% s8 R9 I1 |$ W+ M/ E6 J) d return count;4 d4 y `( J) Y' [+ |
}
" V- M3 f$ U1 Y6 O& } |
|