部落冲突(coc)
Input:coc.in output:coc.out
题目描述:
从前,有一个美丽的村庄,这里环境优美、社会安定、民风淳朴。在这样完美的村庄里,生活着一群完美的野蛮人ljj,他们在这里安家立业,并通过辛勤劳动制造出无限的money。然而,一个不幸的事发生了,一群名为hhh哥布林的恐怖地精部队为了那罪恶的money,竟无比邪恶的袭击了野蛮人ljj的村庄。他们抢走了money,毁坏了建筑,还无情的屠杀了大部分的野蛮人ljj,他们无恶不作、无所不为、简直就不是人。(呸,他们本来就不是人吗!)代表正义的野蛮人们现在无比的angry,为了能一雪前耻,抢回丢失的money,为那些在抵御哥布林hhh的战役中英勇牺牲的先烈们报仇,他们决定进攻hhh哥布林阵地。
现在我们有哥布林阵地的一个r*c的一个地图,在这个地图中,有五种元素:平地、出入口、城墙、加农炮、金库。战争开始时有p个野蛮人,所有野蛮人站在入口处,战争过程的每一秒先后分为野蛮人行动和加农炮攻击两个阶段。
野蛮人行动阶段,野蛮人可以选择移动或抢钱(当野蛮人与某个未被抢光的金库处在同一坐标上时才可选择抢钱),以下为对移动和攻击的说明:
1、若野蛮人选择移动,则他们可以同时向上下左右四个方向移动一步,但他无法走到城墙和加农炮的格子上。
2、每个金库都有一个生命值,第i个金库生命值为hi。若野蛮人选择抢钱,则每个存活的野蛮人都会同时对与他们在同一坐标上的未被抢光的金库造成dd点伤害(dd输入会给出)。假如与野蛮人在同一坐标上的金库原来的剩余血量为hp,则该金库血量会变为(hp-dd*num),num为当前存活的野蛮人数。若金库血量变得小于或等于0,则此金库资源被抢光。(注意:若野蛮人前一秒选择抢钱且当前秒与他们在同一坐标的金库未被抢光,则他们当前秒必须选择抢钱!也就是当野蛮人选择抢某个金库时,他们必须一直抢到金库被抢完为止,不能中途离开。)
加农炮攻击阶段,每一个加农炮会杀死在其攻击范围内一定数量的野蛮人(设第i个加农炮坐标为(xi,yi),野蛮人此时坐标为(xx,yy),则若|xi-xx|<=ti且|yi-yy|<=ti(ti为第i个加农炮的攻击范围),则这群野蛮人在此加农炮攻击范围内)。不同加农炮可杀死的野蛮人的数量也不同,对于第i个加农炮,它可杀死的野蛮人数量为di。
现在野蛮人的目标是抢光所有的金库后回到出入口。若中途某一时间结束后野蛮人全部阵亡,即野蛮人数量小于1,则战争失败,否则若有野蛮人能够安全回到出入口,则战争胜利。
然而现在问题来了---ljj毕竟是野蛮人,他们的脑袋并未成熟,不知道如何进攻,而作为现代无比聪明的文明人,你能做他们的军师吗?作为一名优秀的军师,你要指挥野蛮人们在每一秒做出最优的决策,如果他们能胜利,就让存活的野蛮人数最大化;如果实在无法胜利,就让野蛮人全部英勇牺牲之前能偷的金库尽量多。
输入解释:
第一行6个整数p,r,c,n,m,dd,其中p表示野蛮人的初始数量,r、c表示地图有r行c列,n、m分别表示加农炮的数量、金库的数量,dd表示每个野蛮人每秒对金库的伤害值。
接下来r行每行包含c个字符,描述哥布林阵地的地图;其中“O”、“#”、“X”、“M”、“S”分别表示平地、城墙、加农炮、金库和出入口。(保证出入口不会在任何加农炮的攻击范围内)
接下来n行中第i行四个整数,Xi,Yi,ti,di表示坐标为(Xi,Yi)的加农炮的各项属性。(xi表示第xi行,yi表示第yi列,ti表示攻击范围,di表示每秒能杀死的野蛮人数)
接下来m行中第i行三个整数xi,yi,hi表示坐标为(xi,yi)的金库初始血量为hi。
输入样例(coc.in)
100 4 4 1 2 2
OOOM
OXM#
OOO#
S###
2 2 1 5
1 4 800
2 3 550
输出样例(coc.out):
若野蛮人可以胜利,则第一行输出1,第二行输出野蛮人回到出入口时最多有多少野蛮人存活;若野蛮人无法胜利,则第一行输出-1,第二行输出野蛮人在全部阵亡前最多可以抢光多少个金库。
输出样例:
1
30
数据规模:
对于50%:m<=8
另外20%数据保证野蛮人一定能胜利
对于100%:dd,ti<=10di<=10^9 p,hi<=10^18 r,c<=500 n<=10000 m<=15 1<=xi,Xi<=r 1<=yi,Yi<=c
样例解释:
OOOM
OXM#
OOO#
S###
首先野蛮人移动到(2,3),此时还剩80个野蛮人。接着抢金库,抢完后还剩60个野蛮人。接着他们移动到另一个金库,此时剩余55个野蛮人。抢那个金库,由于无法受到加农炮的攻击,所以野蛮人还是55个。最后回到出入口,只剩30个野蛮人。
若先抢(1,4)金库,则最后只剩25个野蛮人。
附代码:
const yu=1000000;
var
i,j,k,s,n,m,r,c,xx,yy,t,di,hx,hy,tot,ans:longint;
p,dd:int64;
x,y:array[0..15] of longint;
h:array[1..15] of int64;
map:array[1..500,1..500] of char;
mapp:array[1..500,1..500] of longint;
d:array[1..500,1..500] of int64;
dis:array[0..15,0..15] of int64;
way:array[1..4,1..2] of longint=((1,0),(-1,0),(0,1),(0,-1));
data:array[1..yu,1..2] of longint;
dt:array[1 ..500,1..500] of int64;
bz:array[1..500,1..500] of boolean;
f:array[0..15,1..65536] of int64;
mi:array[0..15] of longint;
procedure bfs(xp:longint);
var
i,j,k,ni,nj,pi,pj:longint;
begin
fillchar(dt,sizeof(dt),10);
i:=0; j:=1; dt[x[xp],y[xp]]:=0; bz[x[xp],y[xp]]:=true;
data[1,1]:=x[xp]; data[1,2]:=y[xp];
while i<>j do
begin
inc(i); if i>yu then i:=i-yu;
ni:=data[i,1]; nj:=data[i,2];
for k:=1 to 4 do
begin
pi:=ni+way[k,1]; pj:=nj+way[k,2];
if (pi<=0) or (pi>r) or (pj<=0) or (pj>c) then continue;
if (map[pi,pj]='#') or (map[pi,pj]='X') then continue;
if dt[ni,nj]+d[pi,pj]<dt[pi,pj] then
begin
dt[pi,pj]:=dt[ni,nj]+d[pi,pj];
if map[pi,pj]='S' then dis[xp,0]:=dt[pi,pj] else
if map[pi,pj]='M' then dis[xp,mapp[pi,pj]]:=dt[pi,pj];
if bz[pi,pj]=false then
begin
bz[pi,pj]:=true;
inc(j); if j>yu then j:=j-yu;
data[j,1]:=pi; data[j,2]:=pj;
end;
end;
end;
bz[ni,nj]:=false;
end;
end;
function steal(xi,yi:longint;num,hi:int64):int64;
var
st,gc,sd,en:int64;
l,r,mid:int64;
begin
st:=num*dd; gc:=dd*d[xi,yi];
if gc=0 then exit(num);
l:=1; r:=st div gc;
while l<r do
begin
mid:=(l+r) shr 1; en:=st-(mid-1)*gc;
sd:=(st+en)*mid div 2;
if sd>=hi then r:=mid else l:=mid+1;
end;
en:=st-(l-1)*gc;
sd:=(st+en)*l div 2;
if sd>=hi then exit(num-(l-1)*d[xi,yi]) else exit(0);
end;
procedure max(var a:int64;b:int64);
begin
if b>a then a:=b;
end;
procedure dp;
var
num:int64;
begin
f[0,1]:=p;
for s:=1 to mi[m+1]-1 do
begin
for i:=0 to m do if mi[i] and s>0 then
if s=mi[m+1]-1 then f[0,mi[m+1]]:=f[i,s]-dis[i,0]
else if f[i,s]>0 then
for j:=1 to m do if mi[j] and s=0 then
begin
num:=f[i,s]-dis[i,j];
max(f[j,s+mi[j]],steal(x[j],y[j],num,h[j]));
end;
end;
end;
begin
assign(input,'coc.in'); reset(input);
assign(output,'coc.out'); rewrite(output);
readln(p,r,c,n,m,dd);
mi[0]:=1; for i:=1 to m+1 do mi[i]:=mi[i-1]*2;
for i:=1 to r do
begin
for j:=1 to c do
begin
read(map[i,j]);
if map[i,j]='S' then begin hx:=i; hy:=j; end;
end;
readln;
end;
for i:=1 to n do
begin
read(xx,yy,t,di);
for j:=xx-t to xx+t do if (j>0) and (j<=r) then
for k:=yy-t to yy+t do if (k>0) and (k<=c) then
d[j,k]:=d[j,k]+di;
end;
for i:=1 to m do begin read(x[i],y[i],h[i]); mapp[x[i],y[i]]:=i; end;
x[0]:=hx; y[0]:=hy;
for i:=0 to m do bfs(i);
dp;
if f[0,mi[m+1]]>0 then begin writeln(1); writeln(f[0,mi[m+1]]); end
else
begin
writeln(0);
for s:=1 to mi[m+1] do
for i:=1 to m do if f[i,s]>0 then
begin
tot:=0;
for j:=1 to m do
if mi[j] and s>0 then inc(tot);
if tot>ans then ans:=tot;
end;
writeln(ans);
end;
close(input); close(output);
end.