- 在线时间
- 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 e8 S( K- E) A9 ?; _2 S N0 Y* j4 h8 k" M1 t! [9 w& u
另外发现一个简化公式 n - (n*n/x)。用这个公式计算的结果在一些情况有少量误差。. M; a) {1 [5 i8 Y3 _9 I
我也没有标准答案来判断误差,只是用随机模拟的方式,对指定的 n x 随机几百次试验确定最有可能的值,以下是代码,效率一般,但n在1000以上几百次模拟也能在几秒内搞定:- j- B) u) G, z, |
0 ?* a: G3 T. _9 b4 x; x& A
. p. g) [# s. L7 {' w fC#code:
" C3 e+ ` O/ X- U2 i1 T7 a private void button1_Click(object sender, EventArgs e)$ G t/ B% |' h) U1 q4 R
{
8 o7 _* a, V1 b3 L //新的描述:编号 1 -- X 的停车位,随机停放 n 辆车,无论当前车辆怎样的位置,最少让多少辆车重新停放
& |! W* {* |/ i: H // 就可以使所有车辆连续停放
8 C$ s. R0 A: @1 T. D5 u1 q- }
/ I2 ? a/ j, t/ h# m8 S int n = int.Parse(textBox1.Text);
% e! e; d1 F* Z" h4 ~ e int x = int.Parse(textBox2.Text);
3 {" y M& P0 ~4 J' y3 v' j, U+ [* j* z7 @' s( k
//500次随机模拟的最接近数字,对比公式计算
" W3 m8 M5 V: r5 i int maxValue = 0;
0 o; w# ]( k3 K+ [ for (int i = 0; i < 500; i++)
! H9 p6 q, N& M {! Z2 q5 }1 E+ t2 f2 c- ~+ X, }
int value = randResult(x, n);; [1 @3 ~6 `$ [ ^
if (maxValue < value) maxValue = value;0 ?8 M% G' H |
lbMsg.Text = i.ToString();/ C& K8 o* S) d7 h t
lbMsg.Refresh();/ ~+ b7 |" M6 d; h8 s* \7 w
}) f; h& t1 s, ]% Y! i6 r5 Y1 {
textBox3.Text = maxValue.ToString();
- Q* i' y5 V D7 H, o
) d( L# [, G5 Q# g# F/ u //这是公式计算的结果,据观察大部分正确,少数误差也不超过 3 :)' B6 f; e( d' X4 N7 s8 h1 d u
double newValue = (double)n - ((n*n)/(double)x);, v* q3 C0 A# s5 v# M" {7 U
textBox4.Text = newValue.ToString();
. ?; K1 C1 m, R% V }
; e( J9 ^- q* l* [ f8 A7 W% V- G$ _; V# l$ l6 v
private int randResult(int max, int n)
0 Q% O! t+ J3 z7 B {
7 ] I6 u* ^8 x- s, d+ R2 t if(max <= n) return 0; //error$ { K' P7 l7 L( Q1 v' R% E- n
if (n < 3) return 0; //error
: j* t5 G/ ?( o! s) v if (max < 3) return 0; //error
4 J$ U# Y+ p& P8 g8 c7 X! c
2 S* C% g- s% u' S p3 o int[] lib = new int[max + 1];
7 G4 f5 L0 W) U6 p8 G( @* l9 ?! B' [/ k //随机产生数字来填充
- L: }9 ]! Z9 P$ ]: w3 N* c lib[1] = 1; lib[max] = 1;
/ i# s& O% D5 `1 ~' U) ^6 \, `, t) b int count = n - 2;+ [* D; F1 V+ n0 b5 f) M- J
Random rand = new Random();! X' t3 L* }/ p
while (count > 0): B9 L0 M0 |# |, a0 k
{. P, l) [' W$ ]2 g: P; P ]
int rnd = rand.Next(1, max);7 V: k p0 Z# X5 [1 x3 h5 J% q6 T
if (lib[rnd] == 0)
9 D) ?( E/ Q! e8 n {
0 e8 N8 g3 m @- s2 P# `4 N7 _5 v lib[rnd] = 1;
& M9 J# V) l+ \1 b6 Z count--;
' n8 h5 ]# v2 S1 X0 b& b% }6 I }8 o' R. b! e9 [* F, G3 b+ \2 z
}4 [4 Y0 t( s7 R1 O5 B
//循环检查最密集区域,也就是需要移动最少的区域
& q @( D; w3 T3 P" F int min_space = n;
$ ?8 |; M' x: {: ? for (int i = 1; i <= max - n + 1; i++)9 t" E* W4 T2 z7 K% O
{
6 c% |) _9 P+ I# s6 ^6 O+ { int space = space_count(lib, i, n);
- D r5 j3 X9 W5 x if (min_space > space) min_space = space;
4 q/ ^: B3 X4 j* W3 I. ~3 { }
/ z! a9 y3 i1 S$ Z. S/ j. ]2 e [ return min_space;
& S# N7 x$ u' p }5 I1 ]3 E2 ]5 m5 g2 [4 c
2 u+ R- N" `* F3 {. R5 \8 C" T private int space_count(int[] lib, int start, int n)
: Q+ S3 h5 f' t4 H+ Z { //检查数组start后面n项数据里面有多少个12 Z, s+ O6 U& x% G7 a" x
int count = 0;4 S- T$ u+ E' V4 F1 K
for (int i = start; i < start + n; i++) if (lib[i] == 0) count++;8 J: @3 V, _% a% T
return count;
% K. v2 Z6 t5 z1 h( r2 G, m }' c# P$ j8 b: Y0 J' F2 S" r+ e0 |
|
|