【NOI2008】 赛程安排

题目描述
赛程安排
【问题描述】
随着奥运的来临,同学们对体育的热情日益高涨。在 NOI2008 来临之际,
学校正在策划组织一场乒乓球赛。小 Z 作为一名狂热的乒乓球爱好者,这正是
他大展身手的好机会,于是他摩拳擦掌,积极报名参赛。
本次乒乓球赛采取淘汰赛制,获胜者晋级。恰好有 n (n 是 2 的整数次幂,不
妨设 n = 2k)个同学报名参加,
因此第一轮后就会有 2k-1 个同学惨遭淘汰,
另外 2k-1
个同学晋级下一轮;第二轮后有 2k-2 名同学晋级下一轮,... 依次类推,直到 k
轮后决出冠亚军:
具体的,
每个人都有一个 1~n 的初始编号,
其中小 Z 编号为 1,
所有同学的编号都不同,
他们将被分配到 n 个位置中,然后按照类似下图的赛程
进行比赛:
位置 1        位置 2     位置 3        位置 4        位置 5         位置 6    位置 7         位置 8
位置 1 和位置 2 的    位置 3 和位置 4 的      位置 5 和位置 6 的    位置 7 和位置 8 的
胜者                                   胜者                               胜者                           胜者
          位置 1234 中的胜者                                              位置 5678 的胜者
                                                               冠军
n=8 时比赛的赛程表
为了吸引更多的同学参加比赛,本次比赛的奖金非常丰厚。在第 i 轮被淘汰
的选手将得到奖金 ai 元,
而冠军将获得最高奖金 ak+1 元。显然奖金应满足 a1 < a2
< ... < ak+1.
在正式比赛前的热身赛中,小 Z 连连败北。经过认真分析之后,他发现主要
的失败原因不是他的球技问题,
而是赢他的这几个同学在球风上刚好对他构成相
克的关系,所以一经交手,他自然败阵。小 Z 思索:如果在正式比赛中能够避
开这几位同学,该有多好啊!
假设已知选手两两之间交手的胜率,即选手 A 战胜选手 B 的概率为 PA,B (保
证 PA,B + PB,A=1)。于是小 Z 希望能够通过确定比赛的对阵形势(重新给每个选手
安排位置) 从而能够使得他获得尽可能多的奖金。
,
你能帮助小 Z 安排一个方案,
使得他这场比赛期望获得的奖金最高么?
【输入格式】
这是一道提交答案型试题,所有的输入文件 match*.in 已在相应目录下。
输入文件 match*.in 第一行包含一个正整数 n,表示参赛的总人数,数据保
证存在非负整数 k,满足 2k = n。
接下来 n 行,
每行有 n 个 01 间的实数 Pi,j,, 表示编号为 i 的选手战胜编号
为 j 的选手的概率,每个实数精确到小数点后两位。特别注意 Pi,i = 0.00。
接下来 k+1 行,
每行一个整数分别为晋级各轮不同的奖金, i 行的数为 ai。
【输出格式】
输出文件 match*.out 包括 n 行,第 i 行的数表示位于第 i 个位置的同学的编
号,要求小 Z 的编号一定位于第 1 个位置。
【输入样例】
4
0.00 0.70 0.60 0.80
0.30 0.00 0.60 0.40
0.40 0.40 0.00 0.70
0.20 0.60 0.30 0.00
1
2
3
【输出样例】
1
4
2
3
【样例说明】
第一轮比赛过后,编号为 1 的选手(小 Z)晋级的概率为 80%,编号为 2 的选
手晋级的概率为 60%,编号为 3 的选手晋级的概率为 40%,编号为 4 的选手晋
级的概率为 20%。
第二轮(决赛)
,编号为 1 的选手(小 Z)前两轮均获胜的概率为 80% *
(60%*70% + 40%*60% ) = 52.8%,因此, 小 Z 在第一轮失败的概率 P1=1-0.8=0.2,
第一轮胜出但第二轮败北的概率 P2=0.8-0.528=0.272, 获得冠军的概率 P3=0.528。
从而,期望奖金为 0.2*1 + (0.8-0.528)*2 + 0.528*3 = 2.328。
【如何测试你的输出】
我们提供 match_check 这个工具来测试你的输出文件是否可接受。 使用这
个工具的测试方法是在终端中使用命令:
./match_check 测试数据编号
例如:./match_check 10 表示测试你的 match10.out 是否合法。
调用这个程序后,match_check将根据你得到的输出文件给出测试的结果,
其中包括:
非法退出:
Format error:
Not a permutation:
未知错误;
输出文件格式错误;
输出文件不是一个1~n的排列;
OK.Your answer is xxx:输出文件可以被接受,xxx为对应的期望奖金。
【评分方法】
每个测试点单独评分。
对于每一个测试点,如果你的输出文件不合法,如文件格式错误、输出解不
符合要求等,该测试点得 0 分。否则如果你的输出的期望奖金为 your_ans,参考
期望奖金为 our_ans,我们还设有一个用于评分的参数 d,你在该测试点中的得
分如下:
如果 your_ans > our_ans,得 12 分。
如果 your_ans < our_ans*d,得 1 分。
否则得分为:
⎢ your _ ans − our _ ans * d ⎥    
----------------------------------------       +2
⎢ our _ ans − our _ ans * d *8⎥      
【提示】
“数学期望”
数学期望是随机变量最基本的数字特征之一。它反映随机变量平均取值的大
小,又称期望或均值。它是简单算术平均的一种推广。例如某城市有 10 万个家
庭,没有孩子的家庭有 1000 个,有一个孩子的家庭有 9 万个,有两个孩子的家
庭有 6000 个,有 3 个孩子的家庭有 3000 个,则该城市中任一个家庭中孩子的数
目是一个随机变量,它可取值 0,1,2,3,其中取 0 的概率为 0.01,取 1 的概
率为 0.9, 2 的概率为 0.06, 3 的概率为 0.03,
取
取
它的数学期望为 0×0.01+1×0.9
+2×0.06+3×0.03 等于 1.11,即此城市一个家庭平均有小孩 1.11 个。
本题中期望值的计算:
假设小 Z 在第一轮被打败的概率为 P1,
第一轮胜利且
在第二轮被打败的概率为 P2, 前两轮胜利且在第三轮被打败的概率为 P3......,
那么小 Z 的期望奖金为:
P1 * a1 + P2 * a2 + ...+ Pk+1 * ak+1
【特别提示】
请妥善保存输入文件*.in 和你的输出*.out,及时备份,以免误删。

 

题解

 

解法1:爬山法
  1 (*
  2     *Problem:    NOI2008 赛程安排
  3     *Author :    Chen Yang
  4     *Time   :    2012.5.22
  5     *State  :    81分
  6     *Memo    :    爬山法、调用外部程序
  7 *)
  8 program match;
  9 uses unix;
 10 const climb=20;
 11       change=15000;
 12       chance=10000000;
 13       x='10';
 14 var
 15   n,i:longint;
 16   best:extended;
 17   get:array[0..128] of boolean;
 18   a,ans,this:array[0..128] of longint;
 19 //=================
 20 procedure outit;
 21 begin
 22   assign(output,'tmp'); rewrite(output);
 23   writeln(best:0:2);
 24   for i:=1 to n do writeln(ans[i]);
 25   close(output);
 26 end;
 27 //=================
 28 procedure init;
 29 var
 30   i,t:longint;
 31 begin
 32   fillchar(get,sizeof(get),false);
 33   a[1]:=1; get[1]:=true;
 34   for i:=2 to n do
 35   begin
 36     t:=random(n)+1;
 37     while get[t] do t:=random(n)+1;
 38     get[t]:=true;
 39     a[i]:=t;
 40   end;
 41 end;
 42 //=================
 43 function calc:extended;
 44 var
 45   i:longint;
 46   s:string;
 47 begin
 48   assign(output,'match'+x+'.out'); rewrite(output);
 49   for i:=1 to n do writeln(a[i]);
 50   close(output);
 51   shell('./match_check '+x+' > now.txt');
 52   assign(input,'now.txt'); reset(input);
 53   readln(s);
 54   close(input);
 55   delete(s,1,19);
 56   delete(s,length(s),1);
 57   val(s,calc,i);
 58 end;
 59 //=================
 60 procedure main;
 61 var
 62   i,t,k,x,y:longint;
 63   now,tmp:extended;
 64 begin
 65   best:=0;
 66   for i:=1 to climb do
 67   begin
 68     init;
 69     t:=0; now:=calc; this:=a;
 70     while t<change do
 71     begin
 72       repeat
 73          x:=random(n-1)+2; y:=random(n-1)+2;
 74       until x<>y;
 75       k:=a[x]; a[x]:=a[y]; a[y]:=k;
 76       tmp:=calc;
 77       if tmp>now then
 78       begin
 79         now:=tmp;
 80         this:=a;
 81         t:=0;
 82       end else
 83       begin
 84         if random(chance)>t/35 then
 85         begin
 86           k:=a[x]; a[x]:=a[y]; a[y]:=k;
 87         end;
 88         inc(t);
 89       end;
 90     end;
 91     if now>best then
 92     begin
 93       ans:=this; best:=now;
 94       outit;
 95     end;
 96   end;
 97 end;
 98 //=================
 99 begin
100   randomize;
101   assign(input,'match'+x+'.in'); reset(input);
102   read(n); close(input);
103   main;
104 end.

 

解法2:模拟退火
 1 (*
 2     *Problem:    NOI2008 赛程安排
 3     *Author :    Chen Yang
 4     *Time   :    2012.5.23 9:00 am
 5     *State  :    84分
 6     *Memo    :    模拟退火、调用外部程序
 7 *)
 8 program match;
 9 uses unix;
10 const x='7';
11       dt=0.99996;
12       ct=3500;
13       zero=1e-6;
14 var
15   n,i:longint;
16   best:extended;
17   a:array[0..256] of longint;
18 //==============
19 procedure init;
20 var
21   i:longint;
22 begin
23   assign(input,'tmp'); reset(input);
24   read(best);
25   for i:=1 to n do read(a[i]);
26   close(input);
27 end;
28 //==============
29 procedure outit;
30 var
31   i:longint;
32 begin
33   assign(output,'tmp'); rewrite(output);
34   writeln(best:0:15);
35   for i:=1 to n do writeln(a[i]);
36   close(output);
37 end;
38 //==============
39 function calc:extended;
40 var
41   i:longint;
42   s:string;
43 begin
44   assign(output,'match'+x+'.out'); rewrite(output);
45   for i:=1 to n do writeln(a[i]);
46   close(output);
47   shell('./match_check '+x+' > now.txt');
48   assign(input,'now.txt'); reset(input);
49   readln(s);
50   close(input);
51   delete(s,1,19);
52   delete(s,length(s),1);
53   val(s,calc,i);
54 end;
55 //==============
56 procedure main;
57 var
58   x,y,k:longint;
59   tmp,t,last:extended;
60 begin
61   t:=ct; last:=0;
62   while t>100 do
63   begin
64     repeat
65       x:=random(n-1)+2; y:=random(n-1)+2;
66     until x<>y;
67     k:=a[x]; a[x]:=a[y]; a[y]:=k;
68     tmp:=calc;
69     if tmp>last-zero then
70     begin
71      last:=tmp;
72      if tmp>best then
73      begin
74        best:=tmp;
75        outit;
76      end;
77     end else
78     if random()>exp((tmp-last)/t) then
79     begin
80       k:=a[x]; a[x]:=a[y]; a[y]:=k;
81     end else last:=tmp;
82     t:=t*dt;
83   end;
84 end;
85 //==============
86 begin
87   for i:=1 to 10 do
88   begin
89   randomize;
90   assign(input,'match'+x+'.in'); reset(input);
91   read(n);
92   close(input);
93   init;
94   main;
95   end;
96 end.

 

 1 (*
 2     *Problem:    NOI2008 奥运物流
 3     *Author :    Chen Yang
 4     *Time   :    2012.5.20
 5     *State  :    AC
 6     *Memo    :    树形DP,多重背包
 7 *)
 8 program trans;
 9 uses math;
10 const maxn=65;
11 var
12   n,m,i,len:longint;
13   k,ans:extended;
14   fa:array[0..maxn] of longint;
15   c,kk,ff:array[0..maxn] of extended;
16   f,g:array[0..maxn,0..maxn,0..maxn] of extended;
17 //==================
18 procedure find(x,d:longint);
19 var
20   i,j,k,l:longint;
21 begin
22   for i:=2 to n do if fa[i]=x then find(i,d+1);
23   for k:=min(2,d) to d do
24   begin
25     for i:=0 to m do ff[i]:=0;
26     for i:=2 to n do if fa[i]=x then
27     for j:=m downto 0 do
28     for l:=j downto 0 do
29     if ff[j]<ff[l]+g[i,j-l,k] then ff[j]:=ff[l]+g[i,j-l,k];
30     for i:=0 to m do f[x,i,k]:=ff[i]+kk[k]*c[x];
31   end;
32   if d<>1 then
33   begin
34     for i:=0 to m do ff[i]:=0;
35     for i:=2 to n do if fa[i]=x then
36     for j:=m downto 0 do
37     for l:=j downto 0 do
38     if ff[j]<ff[l]+g[i,j-l,1] then ff[j]:=ff[l]+g[i,j-l,1];
39     for i:=1 to m do f[x,i,1]:=ff[i-1]+kk[1]*c[x];
40   end;
41   for j:=0 to m do
42   for k:=0 to d-1 do
43   if f[x,j,k+1]>f[x,j,1] then g[x,j,k]:=f[x,j,k+1] else g[x,j,k]:=f[x,j,1];
44 end;
45 //==================
46 procedure work(father:longint);
47 var
48   i,j,k:longint;
49   t:extended;
50 begin
51   fillchar(f,sizeof(f),0);
52   fillchar(g,sizeof(g),0);
53   for i:=2 to n do if fa[i]=1 then find(i,1);
54   for i:=0 to m do ff[i]:=0;
55   for i:=2 to n do if fa[i]=1 then
56   for j:=m downto 0 do
57   for k:=j downto 0 do
58   if ff[j]<ff[k]+f[i,j-k,1] then
59   ff[j]:=ff[k]+f[i,j-k,1];
60   t:=0;
61   for i:=0 to m-1 do
62   if t<ff[i] then t:=ff[i];
63   if (father=1)and(ff[m]>t) then t:=ff[m];
64   t:=(t+c[1])/(1-kk[len]);
65   if ans<t then ans:=t;
66 end;
67 //==================
68 procedure main;
69 var
70   i,t:longint;
71 begin
72   kk[0]:=1; for i:=1 to n do kk[i]:=kk[i-1]*k;
73   i:=fa[1]; len:=1;
74   while i<>1 do
75   begin
76     inc(len); t:=fa[i]; fa[i]:=1;
77     work(t);
78     fa[i]:=t; i:=t;
79   end;
80   writeln(ans:0:2);
81 end;
82 //==================
83 begin
84   assign(input,'trans.in'); reset(input);
85   assign(output,'trans.out'); rewrite(output);
86   read(n,m,k);
87   for i:=1 to n do read(fa[i]);
88   for i:=1 to n do read(c[i]);
89   main;
90   close(input); close(output);
91 end.

转载于:https://www.cnblogs.com/datam-cy/archive/2012/05/23/2515345.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值