- 在线时间
- 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次,也就是说保留一个以外都得移动。
, @; f, \& ~: I6 ?4 y! T% s3 C T1 T& E. B7 p$ B* l4 }
另外发现一个简化公式 n - (n*n/x)。用这个公式计算的结果在一些情况有少量误差。$ b5 B! X' x% E' Y0 W" ?7 v, u8 `
我也没有标准答案来判断误差,只是用随机模拟的方式,对指定的 n x 随机几百次试验确定最有可能的值,以下是代码,效率一般,但n在1000以上几百次模拟也能在几秒内搞定:+ H* b8 m* G( j( y& c0 n
3 q, F9 H# D; X6 X ~& ^0 J$ Z# Y: v; ~6 z3 R% M4 ~
C#code:& V, u1 E' ], z X' o0 s3 T0 Y/ b
private void button1_Click(object sender, EventArgs e)
- B1 k2 b+ l* c3 Y5 A) B- R3 C {- j, W# d7 _; ^$ [
//新的描述:编号 1 -- X 的停车位,随机停放 n 辆车,无论当前车辆怎样的位置,最少让多少辆车重新停放6 M2 ~9 f! F& J/ o. ~
// 就可以使所有车辆连续停放7 C6 g( E) m" S: \, k0 K8 [+ A: E
: ]: p' \0 h) E. n2 R4 u
int n = int.Parse(textBox1.Text);
8 A3 w, }9 j9 V4 c2 Z- @ int x = int.Parse(textBox2.Text);, M! T$ Z& {+ m- n
; a+ x1 _$ U7 R# m+ M //500次随机模拟的最接近数字,对比公式计算 `" h3 l0 D5 @. W) T: G, `) _
int maxValue = 0;, M( D, A( Z0 z8 l
for (int i = 0; i < 500; i++): V) _! ], b( Q6 M' B. I! y
{ x. y- e" O7 d
int value = randResult(x, n);
8 x" Y" b0 |7 ]2 H$ w2 F* k if (maxValue < value) maxValue = value;
Z2 d/ H5 Y0 w/ f3 `& R! T- { lbMsg.Text = i.ToString();
2 O" m! K* {1 @: o1 o lbMsg.Refresh();
( d! C6 d6 ^9 [9 _ }
; b3 B2 _" _0 i% e textBox3.Text = maxValue.ToString();0 [0 `5 m' h* Y) v1 O
, c; x) y% M! H' a5 O9 F //这是公式计算的结果,据观察大部分正确,少数误差也不超过 3 :)- { H9 H0 z: \3 N
double newValue = (double)n - ((n*n)/(double)x);
! u0 _7 ?3 G* Z" \+ l' m9 ?" a textBox4.Text = newValue.ToString();
1 `% S! _" N6 m- g) }1 m }8 z9 H: r8 t0 a7 A; T: g
4 i* _; ^* a# ?7 f! e" Y; W
private int randResult(int max, int n)
: ?/ _+ Y% ` i4 D! ~2 x' O {
, q, ?; l4 K" Y. [- @ if(max <= n) return 0; //error
1 J0 p2 o! `; `. v3 a if (n < 3) return 0; //error
: c" t2 q7 B* O* G& m7 M! T if (max < 3) return 0; //error8 S1 W( n. U4 B' o
; V( b9 R8 \& V) w) B. [6 @) l& @ int[] lib = new int[max + 1];. @/ n$ P) C8 t3 o! L
//随机产生数字来填充
8 V* o& t/ k5 W8 O) E3 o+ h, \9 L lib[1] = 1; lib[max] = 1;
8 r0 x4 ?( U% F g# r int count = n - 2;4 t9 y' |: w4 k3 t. d* y- x) t
Random rand = new Random();0 {: s V: r" S8 x% M _
while (count > 0)8 W2 _; v9 J$ }" S" L
{
+ d' ]( I! x3 {4 I k int rnd = rand.Next(1, max);2 m- M5 b* Q" ?
if (lib[rnd] == 0)0 Y& A5 S: e3 M8 }/ m8 ]8 \) i M
{5 T" k# Z( G( I' |- s' O
lib[rnd] = 1;. v* F; q, E3 y( R' }
count--;
: ]) w' \- o, P5 L# P }( b! }- L& h! C
}' X0 Z$ L/ }5 N( u
//循环检查最密集区域,也就是需要移动最少的区域
* D) y! X* O" i1 I int min_space = n;
5 b4 o9 I, w7 }! g3 M/ G2 z6 ^) J2 | for (int i = 1; i <= max - n + 1; i++)
+ E' ~, [" C. U* R8 R {
$ l. x; d/ g# M" {% D int space = space_count(lib, i, n);
% x0 i/ Z2 T* A3 Z if (min_space > space) min_space = space;
1 E; @8 F1 F8 V3 @0 y% q }
0 s- s Q* |8 ?& c6 T3 Z/ ~& Z return min_space;
9 B7 y8 W+ ?$ {7 y: m }
4 ^) H( }. X! _2 z b7 {
* W7 m* V& U" { S3 y private int space_count(int[] lib, int start, int n)
) L! ]' P, P6 @/ S( E { //检查数组start后面n项数据里面有多少个13 r5 q5 C4 x* S% v7 i& M4 i
int count = 0;
; v, j0 d/ e8 y! q y& i0 F for (int i = start; i < start + n; i++) if (lib[i] == 0) count++; a( j7 ~0 A; D5 ]) y% p+ {& ?/ A
return count;
) B- g0 V& S5 T8 |) J }
5 S, U+ O5 K! N" b& i L% [) O |
|