- 在线时间
- 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次,也就是说保留一个以外都得移动。
5 I1 e- D* f; G# M' C- `* I9 U4 U+ D8 i
另外发现一个简化公式 n - (n*n/x)。用这个公式计算的结果在一些情况有少量误差。4 ]1 p5 r. f6 M( y
我也没有标准答案来判断误差,只是用随机模拟的方式,对指定的 n x 随机几百次试验确定最有可能的值,以下是代码,效率一般,但n在1000以上几百次模拟也能在几秒内搞定:
1 j1 y. C/ ]- d1 S7 ~/ N0 F2 C
. ~ m V# Z) Z4 b" G8 h4 h1 E! a2 x1 G5 E
C#code:
: p8 ~" ~% }" D$ x, b private void button1_Click(object sender, EventArgs e)
6 G; J( L% P9 P, V* E {: F; }2 _- V) i# Q- Y# J: ` G
//新的描述:编号 1 -- X 的停车位,随机停放 n 辆车,无论当前车辆怎样的位置,最少让多少辆车重新停放( n0 Y9 I- c8 s3 p0 T
// 就可以使所有车辆连续停放' b, b* |, ^ W5 D( ?( p
4 W( h! |; k R* P: o5 Q0 x int n = int.Parse(textBox1.Text);
5 J) J, S# S% E% T) H4 k4 { int x = int.Parse(textBox2.Text);
, K( _* c# M4 ~1 r- m- D" h; E, T6 ~7 N3 j+ Q5 h
//500次随机模拟的最接近数字,对比公式计算
& Z; ? ~( |' m8 U4 R' ~7 m int maxValue = 0;
7 Q+ {8 G) x! ?% v0 y for (int i = 0; i < 500; i++)
& h3 I$ |8 V$ J {
5 ~8 D* |8 G; }8 B6 u0 c int value = randResult(x, n);
4 X% B v) ~" ?2 d( n: W: l if (maxValue < value) maxValue = value;
- C4 c f& k; ]+ D% ?' @" Q4 ] lbMsg.Text = i.ToString();
9 Y3 q! t( s1 I' z7 D9 s0 [ lbMsg.Refresh();9 t3 f9 H d1 ]/ `# n X
}
# N% |4 ]6 S2 t ^ textBox3.Text = maxValue.ToString();( T% y0 f) G* Z* u
; e6 z% q6 G* F4 J- ^ //这是公式计算的结果,据观察大部分正确,少数误差也不超过 3 :)
, y: J# U+ n0 x+ j } double newValue = (double)n - ((n*n)/(double)x);
$ r, i* M: z! s0 j textBox4.Text = newValue.ToString();* a8 y8 A% Y9 ?2 e% a N) \
}' s. p/ M+ H* N( t1 m9 e$ a
# n- ?/ v# m( r' _8 a/ g private int randResult(int max, int n)8 S0 {' S Z! u3 {+ u5 s% \( d9 n$ s
{+ [2 @% s( ?$ e) E
if(max <= n) return 0; //error8 e6 e( n" v; F8 |, {% P
if (n < 3) return 0; //error2 B0 ~$ W- O/ H: @% W
if (max < 3) return 0; //error. l) \" H1 z& c4 e4 _; B
$ r0 B& [: n- j( @: c, \* V7 o
int[] lib = new int[max + 1];& k, \* u2 m+ V8 c$ W
//随机产生数字来填充
9 `- N$ q* f9 W0 C& B: D6 ~ lib[1] = 1; lib[max] = 1;
1 J2 x& [* E$ ]6 ] int count = n - 2;
+ T! q! D- q+ d& a2 G5 ^+ q4 p Random rand = new Random();" ~( ~6 s! L8 L7 [( V
while (count > 0)
& ?" [1 ^7 b# D$ A8 L. V {
" b8 \+ W! A! i9 i) ~8 R* x4 g int rnd = rand.Next(1, max);
d2 E: s. V$ ^* S$ j if (lib[rnd] == 0). T& b$ t, y2 a0 j5 U
{
/ [+ V% ^! _# {9 Z. ^0 a/ h& X0 V; x lib[rnd] = 1;
$ f* g' z( i) O0 n3 k count--;
. j4 s; U8 f3 [6 w }
* b& }- t; z/ M I, i5 r* O$ R }0 N6 v* U0 l( K8 }
//循环检查最密集区域,也就是需要移动最少的区域
6 H( A. A& A$ R; p' r/ z; Y int min_space = n;
3 ?4 a0 _' `4 y8 c9 O for (int i = 1; i <= max - n + 1; i++)& U( g8 s8 M; l9 o u
{1 c3 |% M9 D: }" `, c1 v2 q5 G+ V4 Y
int space = space_count(lib, i, n);. y- M! `" G- E( n) q) j
if (min_space > space) min_space = space;
5 z$ V' r6 |5 s3 \ }
! c3 m3 H! P9 Q' g4 O# q' C return min_space;
9 ^' D# l4 e* \* X }( X" _+ B. P% g3 f
) O$ e+ l( F+ B1 e# Q, ]1 ~
private int space_count(int[] lib, int start, int n)
9 T; [) K& u) D" c9 R { //检查数组start后面n项数据里面有多少个1
8 @- ~; |1 z3 r int count = 0;
: h3 m4 J9 Q1 x. D; N# w' X/ u for (int i = start; i < start + n; i++) if (lib[i] == 0) count++;
5 R" w9 b' f- i7 v* K7 F- O* B4 g return count;0 Z5 o% u# f- i8 x
}
1 }0 N$ D3 Y! ~ } |
|