題解 [SDOI2010]豬國殺
程式碼成功卡到\(600\)行以內
曾經發誓一天切掉的我打了兩週。。。
先看題
要點還是挺多的,即使是像我這樣熟悉三國殺的同(wán)學(jiā),也要認真看。
首先是基本牌的部分。
殺:在自己的回合內,對攻擊範圍內除自己以外的一名角色使用。如果沒有被『閃』抵消,則造成1點傷害。無論有無武器,殺的攻擊範圍都是1;
直接看看自己的下家跳沒跳,跳了的話就看看是不是一夥然後一刀砍下去,沒跳直接\(return\)。
注意,用了殺之後自己的身份就完全暴露了。
閃:當你受到殺的攻擊時,可以棄置一張閃來抵消殺的效果;
這個沒什麼需要解釋的吧,直接暴力看看有沒有閃就行了。
桃:在自己的回合內,如果自己的體力值不等於體力上限,那麼使用一個桃可以為自己補充一點體力,否則不能使用桃;桃只能對自己使用;在自己的回合外,如果自己的血變為0或者更低,那麼也可以使用;
注意:不能對別人使用!!!
豬哥連弩:武器,攻擊範圍1,出牌階段你可以使用任意張殺;
注意:即使之前有了也要再裝一遍,把之前的頂掉(不愧是豬)。
看上去很簡單,但是細節很多。
首先就是裝上豬哥連弩之後前面的殺也是可以用的,需要\(i=0\)重新掃一遍。
還有題目描述中說保證牌數夠用,不要相信它,牌堆沒了就一直摸最後一張牌。
一個回合只能用一次殺(除非裝了豬哥連弩)。
好了現在\(10\)分到手了。
接下來我們看錦囊牌。
決鬥:出牌階段,對除自己以外任意一名角色使用,由目標角色先開始,自己和目標角色輪流棄置一張殺,首先沒有殺可棄的一方受到1點傷害,另一方視為此傷害的來源;
這個就一個\(while\)
還有傷害來源不是用牌者而是對方。
要判斷是跳反還是跳忠。
南豬入侵:出牌階段,對除你以外所有角色使用,按逆時針順序從使用者下家開始依次結算,除非棄置一張殺,否則受到1點傷害;
這裡判斷一下死了就直接跳過,蒟蒻因為這個調了好幾天。。。
每個人都要判斷。
萬箭齊發:和南豬入侵類似,不過要棄置的不是殺而是閃;
做法和題上說的也一樣,把殺換成閃就完事了。
還是很麻煩的,最後提醒一下按理來說除了桃使用任意一張手牌後都要重新掃一遍,比如說萬箭齊發殺死了你的下家,然後前面的殺有可能就有了目標。
好的現在我們拿到\(30\)分了。
最後一個最噁心的部分——無懈可擊。
orz一下各路用奇偶性來判斷的神仙。
蒟蒻只會遞迴。。。
那麼明確一下,無懈可擊後,自己和對方的身份都已經暴露了。
判斷一下受攻擊的人跳沒跳身份,如果沒跳就直接\(return\)。
記錄一個\(flag\)判斷是在獻殷勤還是表敵意。
然後暴力列舉判斷就行了,找到之後下一層遞迴要\(flag\)^=\(1\)
至此,豬國殺成功\(AC\)。
上程式碼
#define N 2001001
#define MAX 2001
#define re register
#define inf 1e18
#define eps 1e-10
using namespace std;
typedef long long ll;
typedef double db;
inline void read(re ll &ret)
{
ret=0;re char c=getchar();re bool pd=false;
while(!isdigit(c)){pd|=c=='-';c=getchar();}
while(isdigit(c)){ret=(ret<<1)+(ret<<3)+(c&15);c=getchar();}
ret=pd?-ret:ret;
return;
}
ll n,m;
struct zhu
{
ll paishu,leixing,xueliang;//leixing=1為主豬,2為忠豬,3為反豬
char pai[1000001];
bool zhuge,si,tiaozhong,tiaofan,leifan;
}a[11];
char s[N];
char paidui[2001];
ll head;
inline void print()
{
for(re int i=1;i<=n;i++)
{
if(a[i].si)
printf("DEAD\n");
else
{
// cout<<i<<" "<<a[i].xueliang<<endl;
for(re int j=1;j<=a[i].paishu;j++)
{
if(j>1)
putchar(' ');
putchar(a[i].pai[j]);
}
putchar('\n');
}
}
return;
}
inline void init()
{
read(n);
read(m);
for(re int i=1;i<=n;i++)
{
a[i].si=false;
a[i].xueliang=4;
a[i].zhuge=false;
scanf("%s",s+1);
if(s[1]=='M')
a[i].leixing=1;
else if(s[1]=='Z')
a[i].leixing=2;
else
a[i].leixing=3;
for(re int j=1;j<=4;j++)
{
scanf("%s",s+1);
a[i].pai[++a[i].paishu]=s[1];
}
}
for(re int i=1;i<=m;i++)
{
scanf("%s",s+1);
paidui[i]=s[1];
}
}
inline void yongpai(re ll num,re ll pos)
{
for(re int i=pos+1;i<=a[num].paishu;i++)
a[num].pai[i-1]=a[num].pai[i];
a[num].paishu--;
return;
}
inline void jieshu()
{
re bool mp=true,fp=true;
for(re int i=1;i<=n;i++)
{
if(a[i].xueliang!=0&&a[i].leixing==3)
mp=false;
if(a[i].xueliang!=0&&a[i].leixing==1)
fp=false;
}
if(mp)
{
printf("MP\n");
print();
exit(0);
}
if(fp)
{
printf("FP\n");
print();
exit(0);
}
return;
}
inline void mopai(re ll pos,re ll num)
{
for(re int i=1;i<=num;i++)
{
if(++head>m)
head=m;
a[pos].pai[++a[pos].paishu]=paidui[head];
}
return;
}
inline void si(re ll num,re ll laiyuan)
{
// cout<<num<<" "<<laiyuan<<endl;
if(a[num].xueliang>=1)
return;
for(re int i=1;i<=a[num].paishu;i++)
{
if(a[num].pai[i]=='P')
{
yongpai(num,i);
a[num].xueliang++;
break;
}
}
if(a[num].xueliang<1)
{
a[num].si=true;
jieshu();
if(a[num].leixing==3)
mopai(laiyuan,3);
else if(a[num].leixing==2&&a[laiyuan].leixing==1)
{
a[laiyuan].paishu=0;
a[laiyuan].zhuge=false;
}
}
return;
}
inline bool shan(re ll pos)
{
for(re int i=1;i<=a[pos].paishu;i++)
{
if(a[pos].pai[i]=='D')
{
yongpai(pos,i);
return true;
}
}
return false;
}
inline bool sha(re ll pos,re ll num)
{
for(re int i=pos+1;i<=n;i++)
{
if(a[i].si)continue;
if((a[pos].leixing==1&&(a[i].tiaofan||a[i].leifan))||(a[pos].leixing==2&&a[i].tiaofan)||(a[pos].leixing==3&&(a[i].leixing==1||a[i].tiaozhong)))
{
yongpai(pos,num);
if(a[i].tiaofan)
{
a[pos].tiaozhong=true;
a[pos].leifan=false;
}
else if(a[i].tiaozhong||a[i].leixing==1)
a[pos].tiaofan=true;
if(!shan(i))
{
a[i].xueliang--;
si(i,pos);
}
return true;
}
return false;
}
for(re int i=1;i<pos;i++)
{
if(a[i].si)continue;
if((a[pos].leixing==1&&(a[i].tiaofan||a[i].leifan))||(a[pos].leixing==2&&a[i].tiaofan)||(a[pos].leixing==3&&(a[i].leixing==1||a[i].tiaozhong)))
{
yongpai(pos,num);
if(a[i].tiaofan)
{
a[pos].tiaozhong=true;
a[pos].leifan=false;
}
else if(a[i].tiaozhong||a[i].leixing==1)
a[pos].tiaofan=true;
if(!shan(i))
{
a[i].xueliang--;
si(i,pos);
}
return true;
}
return false;
}
}
inline bool wuxie(re ll pos,re ll to,re bool pd)
{
if(!a[to].tiaofan&&!a[to].tiaozhong&&a[to].leixing!=1)return false;
if(pd)
{
re bool flag=false;
for(re int i=pos;i<=n;i++)
{
if(a[i].si)continue;
if((a[to].leixing==1&&(a[i].leixing==3))||(a[to].tiaozhong&&(a[i].leixing==3))||(a[to].tiaofan&&(a[i].leixing==1||a[i].leixing==2)))
continue;
for(re int j=1;j<=a[i].paishu;j++)
{
if(a[i].pai[j]=='J')
{
yongpai(i,j);
if(a[to].leixing==1)
{
a[i].tiaozhong=true;
a[i].leifan=false;
}
else if(a[to].leixing==2)
{
a[i].tiaozhong=true;
a[i].leifan=false;
}
else
{
a[i].tiaofan=true;
a[i].leifan=false;
}
// if((a[i].leixing==1&&a[pos].leixing==2)||(a[i].leixing==2&&(a[pos].leixing==1||a[pos].leixing==2))||(a[i].leixing==3&&a[pos].leixing==3))
return !wuxie(i,to,false);
// else
// return !wuxie(i,to,true);
}
}
}
for(re int i=1;i<pos;i++)
{
if(a[i].si)continue;
if((a[to].leixing==1&&(a[i].leixing==3))||(a[to].tiaozhong&&(a[i].leixing==3))||(a[to].tiaofan&&(a[i].leixing==1||a[i].leixing==2)))
continue;
for(re int j=1;j<=a[i].paishu;j++)
{
if(a[i].pai[j]=='J')
{
yongpai(i,j);
if(a[to].leixing==1)
{
a[i].tiaozhong=true;
a[i].leifan=false;
}
else if(a[to].leixing==2)
{
a[i].tiaozhong=true;
a[i].leifan=false;
}
else
{
a[i].tiaofan=true;
a[i].leifan=false;
}
// if((a[i].leixing==1&&a[pos].leixing==2)||(a[i].leixing==2&&(a[pos].leixing==1||a[pos].leixing==2))||(a[i].leixing==3&&a[pos].leixing==3))
return !wuxie(i,to,false);
// else
// return !wuxie(i,to,true);
}
}
}
return false;
}
else
{
re bool flag=false;
for(re int i=pos;i<=n;i++)
{
if(a[i].si)continue;
if(!((a[to].leixing==1&&(a[i].leixing==3))||(a[to].tiaozhong&&(a[i].leixing==3))||(a[to].tiaofan&&(a[i].leixing==1||a[i].leixing==2))))
continue;
for(re int j=1;j<=a[i].paishu;j++)
{
if(a[i].pai[j]=='J')
{
yongpai(i,j);
if(a[to].leixing==1)
{
a[i].tiaofan=true;
a[i].leifan=false;
}
else if(a[to].leixing==2)
{
a[i].tiaofan=true;
a[i].leifan=false;
}
else
{
a[i].tiaozhong=true;
a[i].leifan=false;
}
return !wuxie(i,to,true);
}
}
}
for(re int i=1;i<pos;i++)
{
if(a[i].si)continue;
if(!((a[to].leixing==1&&(a[i].leixing==3))||(a[to].tiaozhong&&(a[i].leixing==3))||(a[to].tiaofan&&(a[i].leixing==1||a[i].leixing==2))))
continue;
for(re int j=1;j<=a[i].paishu;j++)
{
if(a[i].pai[j]=='J')
{
yongpai(i,j);
if(a[to].leixing==1)
{
a[i].tiaofan=true;
a[i].leifan=false;
}
else if(a[to].leixing==2)
{
a[i].tiaofan=true;
a[i].leifan=false;
}
else
{
a[i].tiaozhong=true;
a[i].leifan=false;
}
return !wuxie(i,to,true);
}
}
}
return false;
}
}
inline bool juedou(re ll pos,re ll num)
{
for(re int i=pos+1;i<=n;i++)
{
if(a[i].si)continue;
if((a[pos].leixing==1&&(a[i].tiaofan||a[i].leifan))||(a[pos].leixing==2&&a[i].tiaofan)||(a[pos].leixing==3&&a[i].leixing==1))
{
yongpai(pos,num);
if(a[i].leixing==3)
{
a[pos].tiaozhong=true;
a[pos].leifan=false;
}
else if(a[i].tiaozhong||a[i].leixing==1)
a[pos].tiaofan=true;
if(wuxie(pos,i,true))
return true;
if(a[pos].leixing==1&&a[i].leixing==2)
{
a[i].xueliang--;
si(i,pos);
return true;
}
re ll turn=i;
while(true)
{
re bool flag=false;
for(re int j=1;j<=a[turn].paishu;j++)
{
if(a[turn].pai[j]=='K')
{
yongpai(turn,j);
flag=true;
break;
}
}
if(!flag)
{
a[turn].xueliang--;
si(turn,turn==pos?i:pos);
return true;
}
if(turn==i)
turn=pos;
else
turn=i;
}
}
}
for(re int i=1;i<pos;i++)
{
if(a[i].si)continue;
if((a[pos].leixing==1&&(a[i].tiaofan||a[i].leifan))||(a[pos].leixing==2&&a[i].tiaofan)||(a[pos].leixing==3&&a[i].leixing==1))
{
yongpai(pos,num);
if(a[i].leixing==3)
{
a[pos].tiaozhong=true;
a[pos].leifan=false;
}
else if(a[i].tiaozhong||a[i].leixing==1)
a[pos].tiaofan=true;
if(wuxie(pos,i,true))
return true;
if(a[pos].leixing==1&&a[i].leixing==2)
{
a[i].xueliang--;
si(i,pos);
return true;
}
re ll turn=i;
while(true)
{
re bool flag=false;
for(re int j=1;j<=a[turn].paishu;j++)
{
if(a[turn].pai[j]=='K')
{
yongpai(turn,j);
flag=true;
break;
}
}
if(!flag)
{
a[turn].xueliang--;
si(turn,turn==pos?i:pos);
return true;
}
if(turn==i)
turn=pos;
else
turn=i;
}
}
}
return false;
}
inline void nanman(re ll pos,re ll num)
{
// cout<<pos<<" "<<num<<endl;
yongpai(pos,num);
for(re int i=pos+1;i<=n;i++)
{
if(a[i].si)continue;
if(wuxie(pos,i,true))continue;
re bool flag=false;
for(re int j=1;j<=a[i].paishu;j++)
{
if(a[i].pai[j]=='K')
{
yongpai(i,j);
flag=true;
break;
}
}
if(!flag)
{
a[i].xueliang--;
if(a[i].leixing==1&&!a[pos].tiaozhong&&!a[pos].tiaofan)
a[pos].leifan=true;
si(i,pos);
}
}
for(re int i=1;i<pos;i++)
{
if(a[i].si)continue;
if(wuxie(pos,i,true))continue;
re bool flag=false;
for(re int j=1;j<=a[i].paishu;j++)
{
if(a[i].pai[j]=='K')
{
yongpai(i,j);
flag=true;
break;
}
}
if(!flag)
{
a[i].xueliang--;
if(a[i].leixing==1&&!a[pos].tiaozhong&&!a[pos].tiaofan)
a[pos].leifan=true;
si(i,pos);
}
}
return;
}
inline void wanjian(re ll pos,re ll num)
{
// cout<<pos<<" "<<num<<endl;
yongpai(pos,num);
for(re int i=pos+1;i<=n;i++)
{
if(a[i].si)continue;
if(wuxie(pos,i,true))continue;
if(!shan(i))
{
a[i].xueliang--;
if(a[i].leixing==1&&!a[pos].tiaozhong&&!a[pos].tiaofan)
a[pos].leifan=true;
si(i,pos);
}
}
for(re int i=1;i<pos;i++)
{
if(a[i].si)continue;
if(wuxie(pos,i,true))continue;
if(!shan(i))
{
a[i].xueliang--;
if(a[i].leixing==1&&!a[pos].tiaozhong&&!a[pos].tiaofan)
a[pos].leifan=true;
si(i,pos);
}
}
return;
}
inline void chupai(re ll pos)
{
re bool chuguosha=false;
for(re int i=1;i<=a[pos].paishu;i++)
{
if(a[pos].si)
return;
if(a[pos].pai[i]=='P')
{
if(a[pos].xueliang<4)
{
yongpai(pos,i);
i=0;
a[pos].xueliang++;
}
}
else if(a[pos].pai[i]=='K'&&(!chuguosha||a[pos].zhuge))
{
if(sha(pos,i))
{
i=0;
chuguosha=true;
}
}
else if(a[pos].pai[i]=='F')
{
if(juedou(pos,i))
i=0;
}
else if(a[pos].pai[i]=='N')
{
nanman(pos,i);
i=0;
}
else if(a[pos].pai[i]=='W')
{
wanjian(pos,i);
i=0;
}
else if(a[pos].pai[i]=='Z')
{
a[pos].zhuge=true;
yongpai(pos,i);
i=0;
}
// cout<<i<<endl;
}
return;
}
/*
『桃(P)』
『殺(K)』
『閃(D)』
『決鬥(F)』
『南豬入侵(N)』
『萬箭齊發(W)』
『無懈可擊(J)』
『豬哥連弩(Z)』
*/
inline void work()
{
re ll num=0;
while(true)
{
num%=n;
num++;
if(a[num].si)
continue;
mopai(num,2);
chupai(num);
}
}
signed main()
{
init();
work();
exit(0);
}
//[SDOI2010]豬國殺