首页 > 代码库 > XJOI游戏
XJOI游戏
Description
暑假到了,次方又可以打网络游戏了。然而在一堆玩家中选择哪些人来刷副本可是一件伤脑筋的事。
现在有n个人,如果同时选择了i和j这两个人,则会产生Aij的战斗力加成。但是如果一共选择了k个人,那么会造成k*(200-k)的网络延迟。团队的总战斗力定义为所有人之间的战斗力加成的和/总的网络延迟。
次方想知道能得到的最大的战斗力是多少。
Input
第一行,一个整数n,表示总人数。
下面n行,每行n列,第i行第j列的元素Aij(0<=Aij<10)表示同时选择i和j带来的战力加成。(Aij=Aji,Aii=0)
Output
一行一个实数,表示战斗力值,保留五位小数。
Sample Input
3 0 7 1 7 0 2 1 2 0
Sample Output
0.01768
HINT
对于30%的数据,有N<=15
对于100%的数据,有N<=50。
题解:
根据数据决定算法。
对于30%的较小数据,采用一定正确的暴力搜索,对于后70%——
模拟退火!
通过random来决定这一次操作是加入一个人还是去除一个人。
若执行这次操作后价值比原来优,则接受;若不如原来优,则以一定的几率t接受这个操作,随搜索的进行,几率t越来越小。
玄学搜索,大致原理是距离答案较远时盲目找,距离答案较近时尽量贪心的找。
代码:
uses math; var a:array[0..50,0..50]of longint; bo,q:array[0..50]of longint; i,j,k,l,n,m:longint; ans:extended; procedure work; var last,tmp,cnt,p,x,del,i:longint; t:extended; begin last:=0; cnt:=0; t:=1; while t>0.00000001 do begin if random(2)=0 then begin if cnt=0 then continue; x:=random(n)+1; if bo[x]=1 then begin del:=0; for i:=1 to n do if bo[i]=1 then del:=del+a[i,x]; tmp:=last-del; if((cnt-1>0)and(ans<tmp/((200-cnt+1)*(cnt-1))))or (random(10000)/10000<t)then begin last:=tmp; if cnt-1>0 then ans:=tmp/((200-cnt+1)*(cnt-1)); dec(cnt); bo[x]:=0; end; end; end else begin if cnt=n then continue; x:=random(n)+1; if bo[x]=0 then begin del:=0; for i:=1 to n do if bo[i]=1 then del:=del+a[i,x]; tmp:=last+del; if(ans<tmp/((200-cnt-1)*(cnt+1)))or(random(10000)/10000<t)then begin last:=tmp; ans:=tmp/((200-cnt-1)*(cnt+1)); inc(cnt); bo[x]:=1; end; end; end; t:=t*0.99999; end; end; procedure ss(x,y,z:longint); var i:longint; begin if x>n then begin if y>0 then ans:=max(ans,z/(y*(200-y))); exit; end; ss(x+1,y,z); for i:=1 to x-1 do if bo[i]=1 then z:=z+a[x,i]; bo[x]:=1; ss(x+1,y+1,z); bo[x]:=0; end; begin randomize; readln(n); for i:=1 to n do for j:=1 to n do read(a[i,j]); if n<=15 then ss(1,0,0)else work; writeln(ans:0:5); end.
XJOI游戏
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。