洛谷P2482 豬國殺
題目描述
《豬國殺》是一種多豬牌類回合制遊戲,一共有三種角色:主豬,忠豬,反豬。每局遊戲主豬有且只有一只,忠豬和反豬可以有多只,每只豬扮演一種角色。
遊戲目的:
主豬(MP):自己存活的情況下消滅所有的反豬。
忠豬(ZP):不惜一切保護主豬,勝利條件與主豬相同。
反豬(AP):殺死主豬。
遊戲過程:
遊戲開始時候,每個玩家手裏都會有4張牌,且體力上限和初始體力都是4。
開始遊戲時,從主豬開始,按照逆時針方向(數據中就是按照編號從1,2,3..n,1..的順序)依次行動。
每個玩家自己的回合可以分為4個階段:
◎摸牌階段:從牌堆頂部摸兩張牌,依次放到手牌的最右邊;
◎出牌階段:你可以使用0張到任意張牌,每次使用牌的時候都使用最靠左的能夠使用的牌。當然,要滿足如下規則:
1.如果沒有豬哥連弩,每個出牌階段只能使用一次“殺”來攻擊;
2.任何牌被使用後被棄置(武器是裝備上);
被棄置的牌以後都不能再用,即與遊戲無關;
各種牌介紹:
每張手牌用一個字母表示,字母代表牌的種類。
◎基本牌:
『桃(P)』:在自己的回合內,如果自己的體力值不等於體力上限,那麽使用一個桃可以為自己補充一點體力,否則不能使用桃;桃只能對自己使用;在自己的回合外,如果自己的血變為0或者更低,那麽也可以使用;
『殺(K)』:在自己的回合內,對攻擊範圍內除自己以外的一名角色使用。如果沒有被『閃』抵消,則造成1點傷害。無論有無武器,殺的攻擊範圍都是1;
『閃(D)』:當你受到殺的攻擊時,可以棄置一張閃來抵消殺的效果;
◎錦囊牌:
『決鬥(F)』:出牌階段,對除自己以外任意一名角色使用,由目標角色先開始,自己和目標角色輪流棄置一張殺,首先沒有殺可棄的一方受到1點傷害,另一方視為此傷害的來源;
『南豬入侵(N)』:出牌階段,對除你以外所有角色使用,按逆時針順序從使用者下家開始依次結算,除非棄置一張殺,否則受到1點傷害;
『萬箭齊發(W)』:和南豬入侵類似,不過要棄置的不是殺而是閃;
『無懈可擊(J)』:在目標錦囊生效前抵消其效果。每次有一張錦囊即將生效時,從使用這張錦囊的豬開始,按照逆時針順序,依次得到使用無懈可擊的機會;
效果:用於決鬥時,決鬥無效並棄置;用於南豬入侵或萬箭齊發時,當結算到某個角色時才能使用,當前角色不需棄置牌並且不會受到傷害(僅對一個角色產生效果);用於無懈可擊時,成為目標的無懈可擊被無效。
◎裝備牌:
『豬哥連弩(Z)』:武器,攻擊範圍1,出牌階段你可以使用任意張殺;
同一時刻最多只能裝一個武器;如果先前已經有了一把武器,那麽之後再裝武器的話,會棄置以前的武器來裝現在的武器;
特殊事件及概念解釋:
◎傷害來源:殺、南豬入侵、萬箭齊發的傷害來源均是使用該牌的豬,決鬥的傷害來源如上;
◎距離:兩只豬的距離定義為沿著逆時針方向間隔的豬數+1。即初始時1和2的距離為1,但是2和1的距離就是n-1。註意一個角色的死亡會導致一些豬距離的改變;
◎玩家死亡:如果該玩家的體力降到0或者更低,並且自己手中沒有足夠的桃使得自己的體力值回到1,那麽就死亡了,死亡後所有的牌(裝備區,手牌區)被棄置;
◎獎勵與懲罰:反豬死亡時,最後一個傷害來源處(即使是反豬)立即摸三張牌。忠豬死亡時,如果最後一個傷害來源是主豬,那麽主豬所有裝備牌、手牌被棄置;
◎註意,一旦達成勝利條件,遊戲立刻結束,因此即使會摸3張牌或者還有牌可以用也不用執行了。
現在,我們已經知道每只豬的角色、手牌,還有牌堆初始情況,並且假設每個角色會按照如下的行為準則進行遊戲,你需要做的就是告訴小豬iPig最後的結果。
幾種行為:
◎獻殷勤:使用無懈可擊擋下南豬入侵、萬箭齊發、決鬥;使用無懈可擊抵消表敵意;
◎表敵意:對某個角色使用殺、決鬥;使用無懈可擊抵消獻殷勤;
◎跳忠:即通過行動表示自己是忠豬。跳忠行動就是對主豬或對某只已經跳忠的豬獻殷勤,或者對某只已經跳反的豬表敵意;
◎跳反:即通過行動表示自己是反豬。跳反行動就是對主豬或對某只已經跳忠的豬表敵意,或者對某只已經跳反的豬獻殷勤;
忠豬不會跳反,反豬也不會跳忠;不管是忠豬還是反豬,能夠跳必然跳;
行動準則:
共性:每個角色如果手裏有桃且生命值未滿,那麽必然吃掉;有南豬入侵、萬箭齊發、必然使用;有裝備必然裝上;受到殺時,有閃必然棄置;響應南豬入侵或者萬箭齊發時候,有殺/閃必然棄置;不會對未表明身份的豬獻殷勤(包括自己);
特性:
◎主豬:主豬會認為沒有跳身份,且用南豬入侵/萬箭齊發對自己造成傷害的豬是“類反豬”(沒傷害到不算,註意“類反豬”並沒有表明身份),如果之後跳了,那麽主豬會重新認識這只豬;對於每種表敵意的方式,對逆時針方向能夠執行到的第一只“類反豬”或者已跳反豬表;如果沒有,那麽就不表敵意;決鬥時會不遺余力棄置殺;如果能對已經跳忠的豬或自己獻殷勤,那麽一定獻;如果能夠對已經跳反的豬表敵意,那麽一定表;
◎忠豬:對於每種表敵意的方式,對逆時針方向能夠執行到的第一只已經跳反的豬表,如果沒有,那麽就不表敵意;決鬥時,如果對方是主豬,那麽不會棄置殺,否則,會不遺余力棄置殺;如果有機會對主豬或者已經跳忠的豬獻殷勤,那麽一定獻;
◎反豬:對於每種表敵意的方式,如果有機會則對主豬表,否則,對逆時針方向能夠執行到的第一只已經跳忠的豬表,如果沒有,那麽就不表敵意;決鬥時會不遺余力棄置殺;如果有機會對已經跳反的豬獻殷勤,那麽一定獻;
限於iPig只會用P++語言寫A + B,他請你用Pigcal(Pascal)、P(C)或P++(C++)語言來幫他預測最後的結果。
輸入描述 Input Description輸入文件第一行包含兩個正整數n(2 <= n <= 5) 和m( m <= 2000),分別代表玩家數和牌堆中牌的數量。數據保證牌的數量夠用。
接下來n行,每行5個字符串,依次表示對第i只豬的角色和初始4張手牌描述。編號為1的肯定是主豬。
再接下來一行,一共m個字符串,按照從牌堆頂部到牌堆底部的順序描述每張牌。
所有的相鄰的兩個字符串都嚴格用1個空格隔開,行尾沒有多余空格。
輸出描述 Output Description輸出數據第一行包含一個字符串代表遊戲結果。如果是主豬勝利,那麽輸出“MP”,否則輸出“FP”。數據保證遊戲總會結束。
接下來n行,第i行是對第i只豬的手牌描述(註意只需要輸出手牌),按照手牌從左往右的順序輸出,相鄰兩張牌用一個空格隔開,行末尾沒有多余空格。如果這只豬已陣亡,那麽只要輸出“DEAD”即可。註意如果要輸出手牌而沒有手牌的話,那麽只需輸出一個空行。
樣例輸入 Sample Input3 10
MP D D F F
ZP N N N D
FP J J J J
F F D D J J F F K D
樣例輸出 Sample OutputFP
DEAD
DEAD
J J J J J D
數據範圍及提示 Data Size & Hint樣例1說明:第一回合主豬沒有目標可以表敵意;接下來忠豬使用了3張南豬入侵,主豬掉了3點體力,並認為該角色為類反豬,3號角色盡管手裏有無懈可擊,但是因為自己未表明身份,所以同樣不能對自己用,乖乖掉3點體力;下一回合反豬無牌可出;接下來主豬對著類反豬爆發,使用4張決鬥,忠豬死亡,結果主豬棄掉所有牌;下來反豬摸到一張殺直接殺死主豬獲勝。
數據說明:一共20組測試數據,每個點5分。10%的數據沒有錦囊牌,另外20%的數據沒有無懈可擊。
蒟蒻的理解:
終於有一天,人們想起了被模擬支配的恐懼--------------進擊的模擬
這是一道會讓你絕望的模擬題,我自己都數不清自己模擬了多少次了,雖然很多地方都是重復的,但是細節很多,大概數了一下,我的PS程序寫了400多行,主要思路就是按照題目給你的要求模擬,使勁模擬,等你模擬完了你就成功了(tuifei)了!!
閃瞎眼程序如下
type
aa=array[0..2010]of char;
pig=record
pai:aa;
blood,num:longint;
zhuge,tiaozhong,tiaofan,leifan,sha:boolean;
shenfen:char;
end;
var
a:array[0..10]of pig;
p:array[0..2010]of char;
n,m,now,fanzeishu:longint;
procedure print;
var
i,j:longint;
begin
for i:=1 to n do
with a[i] do
begin
if blood>0 then
begin
for j:=1 to num do
if j<num then write(pai[j],‘ ‘)
else write(pai[j]);
end
else write(‘DEAD‘);
writeln;
end;
halt;
end;
procedure MPwin;
begin
writeln(‘MP‘);
print;
end;
procedure FPwin;
begin
writeln(‘FP‘);
print;
end;
procedure init;
var
i,j:longint;
begin
readln(n,m);
for i:=1 to n do
with a[i] do
begin
read(shenfen,pai[0]);
if shenfen=‘F‘ then inc(fanzeishu);
for j:=1 to 4 do
read(pai[j+1],pai[j]);
blood:=4;
num:=4;
readln;
end;
a[1].tiaozhong:=true;
if fanzeishu=0 then MPwin;
for i:=1 to m do
read(p[i],p[i+1]);
now:=1;
end;
procedure delete(var pai:aa;x:longint;var num:longint);
var
i:longint;
begin
for i:=x to num-1 do
pai[i]:=pai[i+1];
dec(num);
end;
function next(x:longint):longint;
begin
while true do
begin
x:=x mod n+1;
if a[x].blood>0 then exit(x);
end;
end;
function diyi(x,y:longint):boolean;
begin
exit(((a[x].shenfen=‘F‘) and (a[y].tiaozhong)) or ((a[x].shenfen<>‘F‘) and (a[y].tiaofan)) or ((x=1) and (a[y].leifan)));
end;
function youjun(x,y:longint):boolean;
begin
exit(((a[x].shenfen=‘F‘) and (a[y].tiaofan)) or ((a[x].shenfen<>‘F‘) and (a[y].tiaozhong)));
end;
procedure mopai(x:longint);
begin
if now>m then now:=m;
with a[x] do
begin
inc(num);
pai[num]:=p[now];
inc(now);
end;
end;
procedure tiao(x:longint);
begin
with a[x] do
begin
if shenfen=‘F‘ then tiaofan:=true
else tiaozhong:=true;
leifan:=false;
end;
end;
function chupai(x:longint;c:char):boolean;
var
i:longint;
begin
with a[x] do
begin
for i:=1 to num do
if pai[i]=c then
begin
delete(pai,i,num);
exit(true);
end;
exit(false);
end;
end;
procedure kill(x,y:longint);
begin
if a[y].shenfen=‘F‘ then
begin
mopai(x);
mopai(x);
mopai(x);
end;
if (x=1) and (a[y].shenfen=‘Z‘) then
begin
a[x].num:=0;
a[x].zhuge:=false;
end;
end;
procedure decblood(x:longint);
begin
with a[x] do
begin
dec(blood);
if blood=0 then
begin
if chupai(x,‘P‘)=false then
begin
if shenfen=‘F‘ then dec(fanzeishu);
if fanzeishu=0 then MPwin;
if shenfen=‘M‘ then FPwin;
end
else blood:=1;
end;
end;
end;
function dixiao(x:longint):boolean;
var
i:longint;
begin
i:=next(x);
while i<>x do
begin
if diyi(i,x) and chupai(i,‘J‘) then
begin
tiao(i);
exit(true);
end;
i:=next(i);
end;
exit(false);
end;
procedure gongji(x,y:longint);
begin
if chupai(y,‘D‘)=false then
begin
decblood(y);
if a[y].blood=0 then kill(x,y);
end;
end;
function jiuyuan(x,k:longint):boolean;
var
i:longint;
flag:boolean;
begin
i:=k;
flag:=true;
while true do
begin
if (i=k) and (flag=false) then break;
if i=k then flag:=false;
if (youjun(i,x)) and (chupai(i,‘J‘)) then
begin
tiao(i);
flag:=true;
if not dixiao(i) then exit(true);
end;
i:=next(i);
end;
exit(false);
end;
procedure fight(x,y:longint);
begin
if (x=1) and (a[y].shenfen=‘Z‘) then
begin
decblood(y);
if a[y].blood=0 then kill(x,y);
end
else
if jiuyuan(y,x)=false then
begin
while true do
begin
if chupai(y,‘K‘)=false then
begin
decblood(y);
if a[y].blood=0 then kill(x,y);
exit;
end;
if chupai(x,‘K‘)=false then
begin
decblood(x);
if a[x].blood=0 then kill(y,x);
exit;
end;
end;
end;
end;
procedure nanman(x:longint);
var
i:longint;
begin
i:=next(x);
while i<>x do
begin
if jiuyuan(i,x)=false then
begin
if chupai(i,‘K‘)=false then
begin
decblood(i);
if (i=1) and (not a[x].tiaozhong) and (not a[x].tiaofan) then a[x].leifan:=true;
if a[i].blood=0 then kill(x,i);
end;
end;
i:=next(i);
end;
end;
procedure wanjian(x:longint);
var
i:longint;
begin
i:=next(x);
while i<>x do
begin
if jiuyuan(i,x)=false then
begin
if chupai(i,‘D‘)=false then
begin
decblood(i);
if (i=1) and (not a[x].tiaozhong) and (not a[x].tiaofan) then a[x].leifan:=true;
if a[i].blood=0 then kill(x,i);
end;
end;
i:=next(i);
end;
end;
procedure xingdong(x:longint);
var
i,k:longint;
begin
i:=1;
with a[x] do
while i<=num do
begin
if a[x].blood=0 then exit;
if pai[i]=‘N‘ then
begin
delete(pai,i,num);
nanman(x);
i:=1;
continue;
end;
if pai[i]=‘W‘ then
begin
delete(pai,i,num);
wanjian(x);
i:=1;
continue;
end;
if (pai[i]=‘K‘) and ((not sha) or zhuge) then
begin
k:=next(x);
if diyi(x,k) then
begin
delete(pai,i,num);
tiao(x);
gongji(x,k);
sha:=true;
i:=1;
continue;
end;
end;
if pai[i]=‘F‘ then
begin
k:=next(x);
if x=1 then
begin
while k<>x do
begin
if diyi(x,k) then
begin
delete(pai,i,num);
break;
end;
k:=next(k);
end;
if k<>x then
begin
fight(x,k);
i:=1;
continue;
end;
end;
if shenfen=‘F‘ then
begin
delete(pai,i,num);
tiao(x);
fight(x,1);
i:=1;
continue;
end;
if shenfen=‘Z‘ then
begin
while k<>x do
begin
if diyi(x,k) then
begin
delete(pai,i,num);
break;
end;
k:=next(k);
end;
if k<>x then
begin
tiao(x);
fight(x,k);
i:=1;
continue;
end;
end;
end;
if (pai[i]=‘P‘) and (blood<4) then
begin
inc(blood);
delete(pai,i,num);
i:=1;
continue;
end;
if pai[i]=‘Z‘ then
begin
zhuge:=true;
delete(pai,i,num);
i:=1;
continue;
end;
inc(i);
end;
end;
procedure work;
var
i:longint;
begin
i:=0;
while true do
begin
i:=i mod n+1;
if a[i].blood=0 then continue;
mopai(i);
mopai(i);
a[i].sha:=false;
xingdong(i);
end;
end;
begin
init;
work;
end.
恕我直言,哪天dalao們無聊可以找這題浪費浪費時間。。。。。
洛谷P2482 豬國殺