- 在线时间
- 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次,也就是说保留一个以外都得移动。, T) R" w' `8 d- k4 y
u: W+ b- r8 C9 A0 k; U另外发现一个简化公式 n - (n*n/x)。用这个公式计算的结果在一些情况有少量误差。
S+ B7 Z7 d9 m) J9 H' a. S我也没有标准答案来判断误差,只是用随机模拟的方式,对指定的 n x 随机几百次试验确定最有可能的值,以下是代码,效率一般,但n在1000以上几百次模拟也能在几秒内搞定:
/ G- @9 c8 W2 `# S$ E w
2 @% \6 H; S" ~" R' D9 Q: A# t: ?) s8 D3 E( R6 ?7 q$ z `# r: m
C#code:
- G, A: x" l& q( h' ` Q private void button1_Click(object sender, EventArgs e)( x H# d H8 [
{
2 @- f1 \! z( r% ?& H, N" F! t //新的描述:编号 1 -- X 的停车位,随机停放 n 辆车,无论当前车辆怎样的位置,最少让多少辆车重新停放# Q1 D4 [& `" W7 {7 K5 T* {+ R
// 就可以使所有车辆连续停放% e0 L$ f4 x* P0 Y
/ a2 v+ y0 V2 w5 m- b int n = int.Parse(textBox1.Text);
+ \2 b# t$ c- l0 |" Y9 q1 B: x int x = int.Parse(textBox2.Text);
( W8 N o1 Q. w' Q5 O* }8 W# Y8 J! E( j) q! w* v N
//500次随机模拟的最接近数字,对比公式计算
2 o: e- X4 m5 ^: x- | int maxValue = 0;$ x3 X# D, _0 f+ A: r- `; C, F* V* ~: ]
for (int i = 0; i < 500; i++)/ l' {! k1 @4 R# N
{# w) i: A- j# ?. D
int value = randResult(x, n);
- N) _, Z8 h/ w' H if (maxValue < value) maxValue = value;7 ?" e4 y f0 ]2 F
lbMsg.Text = i.ToString();+ s6 X/ R2 [! Z# ^9 d- T l: b- O
lbMsg.Refresh();
/ k1 z7 f( l/ o- r! v3 o- `: S/ ? }
# g. a7 o" y5 P/ {1 k textBox3.Text = maxValue.ToString();0 d. {* y% |1 y' L& ]7 c: H
. q' T+ O( E9 S //这是公式计算的结果,据观察大部分正确,少数误差也不超过 3 :)( U9 ~5 W" e) _
double newValue = (double)n - ((n*n)/(double)x);7 a% Y' ~6 I7 i8 g
textBox4.Text = newValue.ToString();, Y5 w9 a0 U8 ~/ K, l) r5 D
}/ }& A* ?0 x/ d, ] y
0 R$ A1 S) m) J+ G private int randResult(int max, int n)
) ~5 X# v ]; J {
) `* \9 S4 Y8 E, k0 S if(max <= n) return 0; //error* T% P5 ^4 o+ w- N
if (n < 3) return 0; //error" O5 l. m4 l$ @& v- c/ {' h* m
if (max < 3) return 0; //error- g. k7 z1 Y/ A; L
+ v( o5 r* j' v7 ?9 r! j int[] lib = new int[max + 1];% N. d, J9 u# ~6 _$ R! W" Z0 A* q
//随机产生数字来填充$ c9 w3 D3 h& `( B
lib[1] = 1; lib[max] = 1;
/ s1 y' b* k6 L# m int count = n - 2;! p% N, q9 m( X0 v4 e# V, w
Random rand = new Random();5 X' l9 [9 ^$ ?3 v& R8 B
while (count > 0)7 E7 w$ ?/ Z" m9 Q, a) @
{
, c9 A5 E' m: h# }% u int rnd = rand.Next(1, max);; N1 I/ g( a, i
if (lib[rnd] == 0)
+ t3 l: K1 ~" m! K {
# T2 n+ ?& L' a6 i" s lib[rnd] = 1;
. r# C9 Z/ D( O& P1 ?5 u* o0 m1 R count--;
7 |) Z. G2 w+ X }
' P/ @# d% z* W }! N) _+ P1 }( U1 Y; p/ P" k
//循环检查最密集区域,也就是需要移动最少的区域
4 {! u5 Z/ i- |9 T E* C! x1 N int min_space = n;8 D2 H' r7 S9 {9 z
for (int i = 1; i <= max - n + 1; i++)
0 R1 e' y0 `7 W! P& Z {
$ T7 E5 k3 E# q. r. N9 V int space = space_count(lib, i, n);
' z4 T F% Q( w, |$ G0 A if (min_space > space) min_space = space;
6 Q' y8 V' b5 h( G* [! \5 | }1 f& G! P$ i! \; s
return min_space;$ o- k0 Q7 S) O0 f* ^
}, H) I( R% y) ~' h6 @6 V: H
' O D1 n G' l" M/ S% v6 V
private int space_count(int[] lib, int start, int n)
, @2 D7 Y H* x" B+ }" r7 U1 h { //检查数组start后面n项数据里面有多少个1
( v$ v/ Q0 g9 d int count = 0;- Y/ Z' E) P; E- l7 B
for (int i = start; i < start + n; i++) if (lib[i] == 0) count++;
* c; g2 s( n% `+ v7 @- B* U return count;/ I4 R# s* N% H" N t
}
T0 {5 m+ T- N9 b/ N& U, X6 f |
|