- 在线时间
- 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次,也就是说保留一个以外都得移动。
! K9 Q% ]% n4 Z& w6 z$ L
4 L# g# r9 I1 w. Z另外发现一个简化公式 n - (n*n/x)。用这个公式计算的结果在一些情况有少量误差。
# D" G+ G+ S$ k% ~我也没有标准答案来判断误差,只是用随机模拟的方式,对指定的 n x 随机几百次试验确定最有可能的值,以下是代码,效率一般,但n在1000以上几百次模拟也能在几秒内搞定:" W$ Q( X1 C! w8 x- C
' r3 d6 i9 [- I5 y; p6 \# U" p
7 U2 o( N/ s# _, l" o2 vC#code:
, R0 U1 \% w% t9 g! V% ]8 C private void button1_Click(object sender, EventArgs e)" `2 c2 T- ?9 o
{
! e0 X( o0 M3 ?' m2 A! {" p //新的描述:编号 1 -- X 的停车位,随机停放 n 辆车,无论当前车辆怎样的位置,最少让多少辆车重新停放
2 v; A8 H. ^' w6 L0 g; ` // 就可以使所有车辆连续停放4 ?& o' ^, x% X8 r
2 }9 Q7 P" d/ | int n = int.Parse(textBox1.Text);
$ I; m8 p, b a# y int x = int.Parse(textBox2.Text);/ J6 M' v) d9 _6 @( V
" e9 a, q" q+ ?+ \% q6 v% I
//500次随机模拟的最接近数字,对比公式计算! G* e; o0 o n, @% b3 [
int maxValue = 0;! K5 d. a" |; ~ L2 y9 s4 I
for (int i = 0; i < 500; i++)
& Q" R: k" @+ Y# |$ x) c4 P' } {6 ^, c0 i: Z. _0 E: z3 K1 [/ x
int value = randResult(x, n);
6 c/ ~ D$ I4 M if (maxValue < value) maxValue = value;$ x" u( w. P0 o% j c J$ q* L; B( I
lbMsg.Text = i.ToString();4 C( G A! k2 B1 m# c0 c0 ~' ~
lbMsg.Refresh();
+ z- k! x5 T' e5 T }3 P7 b9 g5 u Y" }: d. ]4 u
textBox3.Text = maxValue.ToString();
/ i+ N( A7 }$ W8 A- P) V1 |
* t- E( Q3 D) k: i //这是公式计算的结果,据观察大部分正确,少数误差也不超过 3 :)
: s* R* M) Q- u+ U double newValue = (double)n - ((n*n)/(double)x);% ]' g* O. ~+ I0 s6 ]4 v7 Q2 r
textBox4.Text = newValue.ToString();
/ c2 T. \$ R, D4 i2 a0 R; X' ~ }" L. W! F. E; ~9 }. M: U$ I" C
! D- q6 T: \7 [% B% z4 O
private int randResult(int max, int n)7 o$ x! {! t6 J8 e9 u- u4 @! x
{
! I0 B, \* Q; W2 S% f0 a( Q if(max <= n) return 0; //error2 |* B$ l) C/ D
if (n < 3) return 0; //error% i1 U( h# J. K8 R) z# \
if (max < 3) return 0; //error
0 l4 z6 m% f& `$ l$ s4 s
6 E- Y. L! Q; u0 n int[] lib = new int[max + 1];/ B* ?- ^; `" J/ L* c( F/ o5 q
//随机产生数字来填充
4 V& L8 j2 ^' \. ~% m5 d6 ?$ b lib[1] = 1; lib[max] = 1;$ L+ Y" H& t: o7 a( o9 a0 S6 p$ y
int count = n - 2;9 B4 m2 H" @$ \
Random rand = new Random();( q7 F/ q) C$ I7 n, h
while (count > 0)1 q0 h+ M' n1 N
{7 F: T( M& e. O7 x; j ~
int rnd = rand.Next(1, max);
0 K3 k+ x9 v4 S* N if (lib[rnd] == 0)
0 V# V. U, J* R2 r7 g0 G- Q {9 @0 g$ m5 W# Q# z: ]. c
lib[rnd] = 1;
1 ?; }$ H* L7 ~2 D( M( ?1 j count--;, e4 |! I% u) D) N9 y; v
}. r3 C' B! V% P/ P1 w5 \8 Q0 H7 E$ n
} J, T3 t2 R, j" Y$ [# J0 W" R( H
//循环检查最密集区域,也就是需要移动最少的区域
4 l- n( B3 ?8 `9 v, Z9 z7 A int min_space = n;
' r* Q; ]$ N' j' X2 a& @) g for (int i = 1; i <= max - n + 1; i++)
: S+ Z( P( n$ q3 X8 L) e% D0 L {
3 l& ?, \/ [; V U% Y# } int space = space_count(lib, i, n); p) T& F% Q, x5 ^- T; N& z
if (min_space > space) min_space = space;
$ [* H6 W) S t7 A; B& E# S }2 Q0 V: n0 a6 j- m' ?
return min_space;2 I" M+ q% l/ E( E. Y
}7 z- X' \' z `. e6 U; }
& p2 K" _0 `- n9 u* {' U) V
private int space_count(int[] lib, int start, int n)+ O9 z! \& Z9 u% R- w6 Q
{ //检查数组start后面n项数据里面有多少个1% L" h7 L! b9 ?( M! g
int count = 0;$ e5 V3 S2 p4 z& t% R- F% q
for (int i = start; i < start + n; i++) if (lib[i] == 0) count++;3 _' X4 [8 o) K3 A" U
return count;
1 ~9 {( P7 g8 r: o }' F3 Q5 a% ?6 K) e" q
|
|