- 在线时间
- 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次,也就是说保留一个以外都得移动。
6 ] q( s0 C4 B: P& P/ O, f3 [2 H3 d8 }( M' ]
另外发现一个简化公式 n - (n*n/x)。用这个公式计算的结果在一些情况有少量误差。" m% g$ X9 |4 y
我也没有标准答案来判断误差,只是用随机模拟的方式,对指定的 n x 随机几百次试验确定最有可能的值,以下是代码,效率一般,但n在1000以上几百次模拟也能在几秒内搞定:
, e* [3 r! k1 P* _
! T3 e: m6 f7 N2 i9 x } _( N j% q3 ]
C#code:! b: [8 ^( ]* x: }, O
private void button1_Click(object sender, EventArgs e)
2 ]! T5 d' n7 e! o# v2 {" ? {
3 C& t) J8 K# G% s //新的描述:编号 1 -- X 的停车位,随机停放 n 辆车,无论当前车辆怎样的位置,最少让多少辆车重新停放, g( Y# m c4 o' |6 E+ A* \
// 就可以使所有车辆连续停放
7 W% G/ E& }# j% O, j+ ?
* S* r) S/ p: V$ l8 T& [+ s) C int n = int.Parse(textBox1.Text);5 @' Q& c9 i( J0 H0 _* r- z) q( p
int x = int.Parse(textBox2.Text);
6 V- V$ p( ]9 I& R8 Q8 c ^; p# }; ]9 c6 f8 T# R1 F+ S4 }/ D
//500次随机模拟的最接近数字,对比公式计算
0 G3 F9 _$ t8 e; b: f0 K6 W9 a2 c9 M int maxValue = 0;
4 c7 V+ m8 X# D3 s9 [ for (int i = 0; i < 500; i++)4 }! y! l/ T1 U1 r* u7 u
{
7 _. m2 p t3 R( X9 {' N int value = randResult(x, n);3 I5 o& C! m S g% Y3 i
if (maxValue < value) maxValue = value;; k( G! b4 e3 m0 a5 c6 L
lbMsg.Text = i.ToString();
! Y( K; M+ f6 Z lbMsg.Refresh();
6 Z* n8 ?# d3 U6 X# |5 H- E }% V9 w1 @7 O" \
textBox3.Text = maxValue.ToString();% a4 C+ O& R) q0 `" p
; e, e9 v, [) X% U1 E# Q% a+ v
//这是公式计算的结果,据观察大部分正确,少数误差也不超过 3 :)
! U+ A* e+ [, L3 r; [ double newValue = (double)n - ((n*n)/(double)x);
3 @4 E5 R/ ?. a6 P7 q textBox4.Text = newValue.ToString();
$ V; E( c' T6 [0 _1 F3 t }+ P, o/ V) F* ~/ ~2 ^, ?" {- v
7 e( C) F; L5 ~4 d! b6 e4 T private int randResult(int max, int n)$ d+ I8 E& a8 ]* X6 ~) J& \, s
{. V& v* y: V& I% Y4 l* u' e
if(max <= n) return 0; //error: L# D' Y; l! b& z" M" H0 k
if (n < 3) return 0; //error$ x# q* m$ }' Z% B3 |3 ?% v
if (max < 3) return 0; //error) H& d$ a. o9 S1 }, d& R
6 @: s9 z1 y6 F9 F' G3 ]. q) _4 w
int[] lib = new int[max + 1];$ l W2 {" Q$ w0 y3 D# w
//随机产生数字来填充
1 Y- F$ u7 a/ |2 W, S7 X9 ]6 [ lib[1] = 1; lib[max] = 1;+ ?- |0 H" P4 e7 ^2 V' \1 x; D
int count = n - 2;
! H2 i5 a4 z' s, m Random rand = new Random();9 |; R2 @! N2 W; V* p. I. m6 i0 c7 t
while (count > 0)/ x2 L% f6 L0 y. A1 W2 X$ V! b% G. Z
{7 L* J6 x4 Q( ~! y+ S; \5 c
int rnd = rand.Next(1, max);5 }% S" O; L% E) H0 b* a6 { i
if (lib[rnd] == 0)" x3 V& F& ^ s
{
g: R6 i6 A- ]+ C4 o+ q( ~ lib[rnd] = 1;
9 j' S( n1 I. _3 x! w% w count--;4 P8 Y2 ]2 c4 H$ @, g0 a
}; V; U7 N( @) s3 x' N' R8 R4 _
}
1 o- X8 M! m3 q v* I3 h //循环检查最密集区域,也就是需要移动最少的区域! d2 b3 ]7 r/ q
int min_space = n;
5 [) h0 e" A( h7 G, s* v! t/ C for (int i = 1; i <= max - n + 1; i++)
# Q; G* r1 Q- j+ W {
& \$ u4 G1 ]2 g8 c int space = space_count(lib, i, n);
2 C- z' h+ M u# t1 w if (min_space > space) min_space = space;
/ V Y$ X* B( f" [ J# Z, a }
4 e0 i0 e. U) \2 M# \# v7 ^' f return min_space;
$ [$ H9 T6 ~' X) c. Q6 N }
3 c8 K: N3 F! @& @+ |6 Z4 K' U, a6 H
+ [/ x* c {% l$ Z private int space_count(int[] lib, int start, int n)% R& ?5 S8 {; A7 y, W3 ]- |
{ //检查数组start后面n项数据里面有多少个1
4 s" z# E4 s+ i5 E/ D int count = 0;$ ] f+ Q4 N- v
for (int i = start; i < start + n; i++) if (lib[i] == 0) count++;+ L f0 S+ F% V t
return count;% B) f; e7 n2 H) l8 I0 C
}& _+ i$ X. C" e6 B
|
|