- 在线时间
- 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次,也就是说保留一个以外都得移动。
- Q# a+ z8 P! P% O) s% U, S& j3 f, R4 [( M! J- o0 M9 u8 z
另外发现一个简化公式 n - (n*n/x)。用这个公式计算的结果在一些情况有少量误差。# d7 L. t6 e( K. [0 o" e0 \: |
我也没有标准答案来判断误差,只是用随机模拟的方式,对指定的 n x 随机几百次试验确定最有可能的值,以下是代码,效率一般,但n在1000以上几百次模拟也能在几秒内搞定:
: ?2 a$ [0 } d; Q) v% j) u( d& Y9 l x7 |8 R
, l M8 ^0 A% V: g0 m3 \7 G$ `C#code:3 v: v! d7 a% }1 V; l- b1 c
private void button1_Click(object sender, EventArgs e); x& \5 |1 l/ f! K
{6 c6 x8 ?3 B' |. o' T; A
//新的描述:编号 1 -- X 的停车位,随机停放 n 辆车,无论当前车辆怎样的位置,最少让多少辆车重新停放
8 a5 e0 V6 o& v // 就可以使所有车辆连续停放) x& h6 d4 b8 g- R; Y9 l8 Z9 k+ M
8 u' p( ?+ ]5 n* U6 v# | int n = int.Parse(textBox1.Text);
0 ^. {/ c3 b ?- f0 ]' f int x = int.Parse(textBox2.Text);4 t- e( c- H0 [5 f. \
( U- l H- C0 p% C8 A8 G
//500次随机模拟的最接近数字,对比公式计算
; U4 o7 {2 i' h8 R$ y8 k3 M int maxValue = 0;4 [0 A& _3 J2 e% F, }3 H7 s& p
for (int i = 0; i < 500; i++)
% M- M+ R) [9 I {$ ]$ {6 L) a6 p. V
int value = randResult(x, n);
' r7 a8 @) x/ ~+ j# p if (maxValue < value) maxValue = value;' r& }3 y$ W+ |" z) C0 m
lbMsg.Text = i.ToString();% g$ W. `4 Y# b' D( u/ ]2 U
lbMsg.Refresh();
& b) c% k+ R2 M# K* X$ g }
$ f `' F/ Y; r4 D0 N, ^% C textBox3.Text = maxValue.ToString();$ }( o6 S5 K; A6 [
) |! _6 f( t2 k+ c/ }3 h! O //这是公式计算的结果,据观察大部分正确,少数误差也不超过 3 :)( a8 Q6 f; }1 |' K5 o, U
double newValue = (double)n - ((n*n)/(double)x);/ p1 q+ t) \, i _
textBox4.Text = newValue.ToString();
$ l- T5 M+ D7 u: { }
5 b7 {' B4 A3 G" S! e% ]. F) c& O: m* D9 r5 `9 \
private int randResult(int max, int n)
5 I: n( [1 ~! v7 B {
( W" o N* r1 V, R! r* c9 l% Y& o if(max <= n) return 0; //error
! J( X5 Q+ P& N# P6 W; \ if (n < 3) return 0; //error
. a' t7 B+ b4 ^% G9 i t if (max < 3) return 0; //error( D, z) B1 W2 g/ V) ]4 n1 b" E2 V, k
! b& b4 f0 u5 G7 Z2 u+ F8 }
int[] lib = new int[max + 1]; Y1 Y6 s. R4 o2 j; [
//随机产生数字来填充0 v: v% e' w" E9 {
lib[1] = 1; lib[max] = 1;
/ o8 d& M& [5 ]* V, P$ N int count = n - 2;
! A- N! ^. t: U. ?$ ?0 a$ A7 n, O Random rand = new Random();7 a7 c# Y0 D0 r* W( M: F" D- U
while (count > 0)
6 b8 v& ^) d' X5 ?% S; T) M8 Z {& s1 m/ l. j# }% P$ V" R/ a
int rnd = rand.Next(1, max);
- d& P2 z4 p. _+ x if (lib[rnd] == 0)* [& w! Z/ d& ], ~ z% {
{' N1 m# n ?0 ?9 X: k
lib[rnd] = 1;
- ^# {; K& c' }% J' j: N* ?& H" d; ^ count--;( j" N. ]0 b p' Y
}" \7 i, O3 {! M0 t+ j
}( `- V% v) c0 l5 c4 ]) o: ?. N. M
//循环检查最密集区域,也就是需要移动最少的区域0 }0 R$ Q6 f4 d. \0 Q* z- `
int min_space = n;! i! w# f' }) D( V% V
for (int i = 1; i <= max - n + 1; i++): m: ]$ ]! S* E9 L, O, o) J
{
6 W1 J6 Q+ y/ C int space = space_count(lib, i, n);
- G: E- w1 Y4 D6 v6 M if (min_space > space) min_space = space;$ c) h- k: w" w& u: t
}) ^! k2 w$ F, ~
return min_space;# p. Q' I5 E' a& c! [1 i7 U( a% r% g
}% E! r' X) G! Q/ t
! R! Q- t# s- i1 A. x
private int space_count(int[] lib, int start, int n)
4 y* W4 d7 K" @) e4 t6 l { //检查数组start后面n项数据里面有多少个1
9 B I3 ~$ G7 ~; a1 {4 O int count = 0;8 b1 H! n7 a, v) L, {7 Y- E
for (int i = start; i < start + n; i++) if (lib[i] == 0) count++;$ m7 f1 f6 M+ a; E
return count;
- m) f* W. G# w/ m; w, B }
! ~7 @* q0 e2 K; d |
|