[LOJ2885 / luoguP2482 / bzoj1972] 猪国杀
大模拟,要注意一下数据貌似有问题,抽牌的时候没牌了就重复抽取最后一张、
然后貌似只有loj是完整的题面
然后就是各种读题&码
- 先附上带调试信息的代码
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=20010;
char getch(){
char x=0,res;while(x<'A'||x>'Z')x=getchar();
res=x;while(x>='A'&&x<='Z')x=getchar();
return res;
}
char x;
const int INF=998244353;
bool GAMEOVER=false;
char surfaceidentity[30];
//"functions
int n,m,cont;
bool if_enemy(int,int);
bool if_friend(int,int);
int find_enemy(int);
void playerdie(int);
void kill(int,int);
void invade(int);
void arrow(int);
void duel(int,int);
//"pre define
struct pig{
char identity,equipment;
int killtime,life,playerID,lplayer,rplayer;
bool deadalready;
struct handcard{
int nxt,pre;
char type;bool drewed;
}card[N];
int R,tot;
//"functions below are a player's basic action including getting&drewing cards,doing terms etc.
inline void getcard(){
++cont;
if(cont<=m)x=getch();
card[++tot].type=x;
card[tot].pre=R;
//card[tot].nxt=0;
card[R].nxt=tot;R=tot;
//for(int i=1;i<=R;i++)cout<<card[i].nxt<<' ';
//cout<<endl;
}
void drewcard(int x){
card[x].drewed=true;
//cout<<endl<<"drew!";
//cout<<x<<' '<<card[x].drewed<<"|"<<identity;
//cout<<"{}"<<card[1].drewed<<endl;
card[card[x].pre].nxt=card[x].nxt;
card[card[x].nxt].pre=card[x].pre;
if(R==x)R=card[x].pre;
//cout<<"ID:"<<playerID<<" x"<<x<<'|'<<card[0].nxt<<endl<<endl;
}
inline int findcard(char x){
//if(x=='D')cout<<playerID<<"finding D>>";
//if(x=='D')cout<<card[0].nxt<<endl;
int pos=card[0].nxt;
while(pos) {
if(card[pos].type==x)return pos;
pos=card[pos].nxt;
}
return -1;
}
inline void MYTERM(){
//cout<<"ID:"<<playerID<<endl;
int pos=card[0].nxt;
while(pos) {
//print();
//cout<<card[1].drewed<<endl;
if(GAMEOVER||deadalready)return;
//cout<<pos<<' '<<card[pos].drewed<<":"<<identity;
if(card[pos].drewed==true){pos=card[pos].nxt;continue;}
//"judge what to do
//print();
//cout<<pos<<"deciding on:"<<card[pos].type<<endl;
if(decide(card[pos].type,pos))return;
//cout<<card[pos].nxt<<endl;
//cout<<pos<<endl;
//for(int i=1;i<=R;i++)cout<<card[i].nxt<<' ';
//cout<<endl;
pos=card[pos].nxt;
}
}
//"functions below are a player's reaction in different situations.
inline void drewall(){
equipment=0;
killtime=0;
int pos=card[0].nxt;
while(pos) {
//cout<<pos<<endl;
drewcard(pos);
pos=card[pos].nxt;
}
R=0;
}
inline void dead(pig &killer){
//cout<<playerID<<' '<<life<<endl;
int id=findcard('P');
if(~id)life++,drewcard(id);
else{
playerdie(playerID);
//cout<<killer.playerID<<"kill"<<playerID<<endl;
if(GAMEOVER)return;
if(identity=='Z'&&killer.identity=='M'){
killer.drewall();
}else if(identity=='F'){
for(int i=1;i<=3;i++){
killer.getcard();
}
}
}
}
//"functions below are a player's dicision on giving cards
inline bool decide(char cardtype,int id){
if(cardtype=='P'){
if(life<4){
drewcard(id),life++;
MYTERM();
return true;
}
}else if(cardtype=='K'){
int tar=-1;
//cout<<playerID<<' '<<rplayer<<">>>";
//cout<<if_enemy(playerID,rplayer)<<' '<<surfaceidentity[rplayer]<<endl;
if(if_enemy(playerID,rplayer)){
tar=rplayer;
//cout<<"findtar:"<<tar<<endl;
}
if(~tar&&killtime>0){
//cout<<"drewkill\n";
drewcard(id);
killtime--;
kill(playerID,tar);
MYTERM();
return true;
}
return false;
}else if(cardtype=='D'){
return false;
}else if(cardtype=='F'){
if(identity=='F') { drewcard(id); duel(playerID,1); MYTERM(); return true;}
int tar=find_enemy(playerID);
if(~tar){
drewcard(id);
duel(playerID,tar);
MYTERM();
return true;
}
return false;
}else if(cardtype=='N'){
drewcard(id);
invade(playerID);
MYTERM();
return true;
}else if(cardtype=='W'){
drewcard(id);
arrow(playerID);
MYTERM();
return true;
}else if(cardtype=='J'){
return false;
}else if(cardtype=='Z'){
equipment='Z';
killtime=INF;
drewcard(id);
MYTERM();
return true;
}
return false;
}
//"printresult
void print(){
if(deadalready){
printf("DEAD");
}
else{
int pos=card[0].nxt;
while(pos) {
printf("%c ",card[pos].type);
pos=card[pos].nxt;
}
}
printf("\n");
}
}player[30];
int Fcnt;
//"PLAY BOARD >>> here are functions to run the game by rules
void win(char side){
printf("%cP\n",side);
GAMEOVER=true;
}
void playerdie(int id){
// cout<<id<<" is killed!!!!!"<<endl;
player[id].deadalready=true;
if(player[id].identity=='F')Fcnt--;
player[player[id].rplayer].lplayer=player[id].lplayer;
player[player[id].lplayer].rplayer=player[id].rplayer;
if(Fcnt==0)win('M');
if(player[id].identity=='M')win('F');
}
bool if_enemy(int u,int v){
//cout<<u<<' '<<v<<endl;
//cout<<player[u].identity<<' '<<surfaceidentity[v]<<' '<<player[v].identity<<endl;
if(player[u].identity=='M')
if(surfaceidentity[v]=='M'||surfaceidentity[v]=='F')return true;
if(player[u].identity=='Z')
if(surfaceidentity[v]=='F')return true;
if(player[u].identity=='F')
if(surfaceidentity[v]=='Z'||player[v].identity=='M')return true;
return false;
}
bool if_friend(int u,int v){
if(player[u].identity=='M')
if(surfaceidentity[v]=='Z')return true;
if(player[u].identity=='Z')
if(surfaceidentity[v]=='Z'||player[v].identity=='M')return true;
if(player[u].identity=='F')
if(surfaceidentity[v]=='F')return true;
return false;
}
inline int find_enemy(int ID){
int pos=player[ID].rplayer;
while(pos!=ID){
if(if_enemy(ID,pos))return pos;
pos=player[pos].rplayer;
}
return -1;
}
void kill(int u,int v){
//cout<<u<<"is killing "<<v<<endl;
int cardid=player[v].findcard('D');
//cout<<cardid<<endl;
if(~cardid){
player[v].drewcard(cardid);
}
else player[v].life--;
if(player[v].life<=0)player[v].dead(player[u]);
if(u!=1)surfaceidentity[u]=player[u].identity;
}
bool cancleopt(int ID,int former,bool ifharm){
//cout<<ID<<' '<<former<<' '<<ifharm<<endl;
int pos=former;
bool res=false;
while(true){
if(GAMEOVER)return true;
//if(cancleopt(pos,former,1))continue;
if(!(ifharm&&if_friend(pos,ID)) && !(!ifharm&&if_enemy(pos,ID))){
pos=player[pos].rplayer;
if(pos==former)break;
continue;
}//"should not play
int cardid=player[pos].findcard('J');
if(~cardid){
//cout<<pos<<"drew his DEFENCE to" << ID <<endl;
if(pos!=1)surfaceidentity[pos]=player[pos].identity;
player[pos].drewcard(cardid);
res=true;
if(cancleopt(ID,pos,ifharm^1))res=false;
break;
}
pos=player[pos].rplayer;
if(pos==former)break;
}
return res;
}
void invade(int ID){
int pos=player[ID].rplayer;
//cout<<"INVADING"<<'|'<<"starter :"<<ID<<endl;
//player[1].print();
//cout<<endl;
while(pos!=ID){
if(GAMEOVER)return;
//cout<<"judge on pos"<<pos<<endl;
if(cancleopt(pos,ID,1)){pos=player[pos].rplayer;continue;}
int cardid=player[pos].findcard('K');
if(~cardid)
player[pos].drewcard(cardid);
else {
player[pos].life--;
//cout<<pos<<' '<<"damaged"<<endl;
if(player[pos].identity=='M')if(surfaceidentity[ID]!=player[ID].identity)surfaceidentity[ID]='M';
if(player[pos].life<=0)player[pos].dead(player[ID]);
}
pos=player[pos].rplayer;
}
}
void arrow(int ID){
int pos=player[ID].rplayer;
//cout<<"ARROWING"<<'|'<<"starter : "<<ID<<endl;
while(pos!=ID){
//cout<<pos<<' '<<GAMEOVER<<endl;
if(GAMEOVER)return;
if(cancleopt(pos,ID,1)){pos=player[pos].rplayer;continue;}
int cardid=player[pos].findcard('D');
if(~cardid)
player[pos].drewcard(cardid);
else {
player[pos].life--;
//cout<<pos<<' '<<"damaged"<<endl;
if(player[pos].identity=='M')if(surfaceidentity[ID]!=player[ID].identity)surfaceidentity[ID]='M';
if(player[pos].life<=0)player[pos].dead(player[ID]);
}
pos=player[pos].rplayer;
}
}
void duel(int ID1,int ID2){
//cout<<"HAVING A DUEL WITH "<<ID1<<'&'<<ID2<<endl;
if(ID1!=1)surfaceidentity[ID1]=player[ID1].identity;
if(cancleopt(ID2,ID1,1))return;
if(player[ID2].identity=='Z'&&player[ID1].identity=='M'){
player[ID2].life--;
if(player[ID2].life<=0)player[ID2].dead(player[ID1]);
return;
}
int atk=ID1,dfn=ID2;
while(true){
swap(atk,dfn);
int cardid=player[atk].findcard('K');
if(~cardid){
player[atk].drewcard(cardid);
}else {
break;
}
}
//cout<<atk<<"lose!"<<endl;
player[atk].life--;
if(player[atk].life<=0)player[atk].dead(player[dfn]);
}
inline void playing(){
int pos=1;
while(!GAMEOVER){
player[pos].getcard();player[pos].getcard();
//cout<<pos<<">>"<<player[pos].identity<<endl;
//player[pos].print();
//cout<<"having his term..."<<endl;
player[pos].killtime=player[pos].equipment=='Z'?INF:1;
player[pos].MYTERM();
//for(int i=1;i<=n;i++)cout<<">>>"<<player[i].identity<<" "<<surfaceidentity[i]<<' '<<player[i].life<<endl;
//cout<<pos<<">>"<<player[pos].identity<<endl;
//player[pos].print();
pos=player[pos].rplayer;
}
}
inline void init(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
player[i].playerID=i;
player[i].life=4;
player[i].lplayer=i-1,player[i].rplayer=i+1;
player[i].identity=getch();
//cout<<player[i].identity<<endl;
if(player[i].identity=='F')Fcnt++;
for(int p=1;p<=4;p++){cont=0;player[i].getcard();}
}
player[1].lplayer=n,player[n].rplayer=1;
surfaceidentity[1]='Z';
}
int main()
{
init();
cont=0;
playing();
for(int i=1;i<=n;i++){
player[i].print();
}
}
- 以下是各种
压行加 魔改之后的代码
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=20010;
char getch(){
char x=0,res;while(x<'A'||x>'Z')x=getchar();
res=x;while(x>='A'&&x<='Z')x=getchar();
return res;
}
char x;
const int INF=998244353;
bool GAMEOVER=false;
char surfaceidentity[30];
int n,m,cont;
//"functions
bool if_enemy(int,int);
bool if_friend(int,int);
int find_enemy(int);
void playerdie(int);
void kill(int,int);
void invade(int);
void arrow(int);
void duel(int,int);
//"pre define
struct pig{
//"informations
char identity,equipment;
int killtime,life,playerID,lplayer,rplayer;
bool deadalready;
struct handcard{
int nxt,pre;
char type;bool drewed;
}card[N];
int R,tot;
//"functions below are a player's basic action including getting&drewing cards,doing terms etc.
inline void getcard(){
++cont;
if(cont<=m)x=getch();
card[++tot].type=x; card[tot].pre=R;
card[R].nxt=tot; R=tot;
}
void drewcard(int x){
card[x].drewed=true;
card[card[x].pre].nxt=card[x].nxt; card[card[x].nxt].pre=card[x].pre;
if(R==x) R=card[x].pre;
}
inline int findcard(char x){
int pos=card[0].nxt;
while(pos) {
if(card[pos].type==x)return pos;
pos=card[pos].nxt;
}
return -1;
}
inline void MYTERM(){
int pos=card[0].nxt;
while(pos) {
if(GAMEOVER||deadalready)return;
if(card[pos].drewed==true){pos=card[pos].nxt;continue;}
//"judge what to do
if(decide(card[pos].type,pos))return;
pos=card[pos].nxt;
}
}
//"functions below are a player's reaction in different situations.
inline void drewall(){
equipment=0,killtime=0;
int pos=card[0].nxt;
while(pos) {
drewcard(pos);
pos=card[pos].nxt;
}
R=0;
}
inline void dead(pig &killer){
int id=findcard('P');
if(~id)life++,drewcard(id);
else{
playerdie(playerID);
if(GAMEOVER)return;
if(identity=='Z'&&killer.identity=='M')
killer.drewall();
else if(identity=='F')
for(int i=1;i<=3;i++)
killer.getcard();
}
}
//"functions below are a player's dicision on giving cards
inline bool decide(char cardtype,int id){
if(cardtype=='P'){
if(life<4){
drewcard(id),life++;
MYTERM();
return true;
}
}else if(cardtype=='K'){
int tar=-1;
if(if_enemy(playerID,rplayer)) tar=rplayer;
if(~tar&&killtime>0){
drewcard(id);
killtime--;
kill(playerID,tar);
MYTERM();
return true;
}
return false;
}else if(cardtype=='D'){
return false;
}else if(cardtype=='F'){
if(identity=='F') { drewcard(id); duel(playerID,1); MYTERM(); return true;}
int tar=find_enemy(playerID);
if(~tar){
drewcard(id);
duel(playerID,tar);
MYTERM();
return true;
}
return false;
}else if(cardtype=='N'){
drewcard(id);
invade(playerID);
MYTERM();
return true;
}else if(cardtype=='W'){
drewcard(id);
arrow(playerID);
MYTERM();
return true;
}else if(cardtype=='J'){
return false;
}else if(cardtype=='Z'){
equipment='Z';
killtime=INF;
drewcard(id);
MYTERM();
return true;
}
return false;
}
//"printresult
void print(){
if(deadalready)
printf("DEAD");
else{
int pos=card[0].nxt;
while(pos) {
printf("%c ",card[pos].type);
pos=card[pos].nxt;
}
}
printf("\n");
}
}player[30];
//"PLAY BOARD >>> here are functions to run the game by rules
int Fcnt;
void win(char side){
printf("%cP\n",side);
GAMEOVER=true;
}
void playerdie(int id){
player[id].deadalready=true;
if(player[id].identity=='F')Fcnt--;
player[player[id].rplayer].lplayer=player[id].lplayer;
player[player[id].lplayer].rplayer=player[id].rplayer;
if(Fcnt==0)win('M');
if(player[id].identity=='M')win('F');
}
//"judge the relationship
bool if_enemy(int u,int v){
if(player[u].identity=='M')
if(surfaceidentity[v]=='M'||surfaceidentity[v]=='F')return true;
if(player[u].identity=='Z')
if(surfaceidentity[v]=='F')return true;
if(player[u].identity=='F')
if(surfaceidentity[v]=='Z'||player[v].identity=='M')return true;
return false;
}
bool if_friend(int u,int v){
if(player[u].identity=='M')
if(surfaceidentity[v]=='Z')return true;
if(player[u].identity=='Z')
if(surfaceidentity[v]=='Z'||player[v].identity=='M')return true;
if(player[u].identity=='F')
if(surfaceidentity[v]=='F')return true;
return false;
}
inline int find_enemy(int ID){
int pos=player[ID].rplayer;
while(pos!=ID){
if(if_enemy(ID,pos))return pos;
pos=player[pos].rplayer;
}
return -1;
}
//"cards
void kill(int u,int v){
int cardid=player[v].findcard('D');
if(~cardid){
player[v].drewcard(cardid);
}
else player[v].life--;
if(player[v].life<=0)player[v].dead(player[u]);
if(u!=1)surfaceidentity[u]=player[u].identity;
}
bool cancleopt(int ID,int former,bool ifharm){
int pos=former;
bool res=false;
while(true){
if(GAMEOVER)return true;
if(!(ifharm&&if_friend(pos,ID)) && !(!ifharm&&if_enemy(pos,ID))){
pos=player[pos].rplayer;
if(pos==former)break;
continue;
}//"should not play
int cardid=player[pos].findcard('J');
if(~cardid){
if(pos!=1)surfaceidentity[pos]=player[pos].identity;
player[pos].drewcard(cardid);
res=true;
if(cancleopt(ID,pos,ifharm^1))res=false;
break;
}
pos=player[pos].rplayer;
if(pos==former)break;
}
return res;
}
void invade(int ID){
int pos=player[ID].rplayer;
while(pos!=ID){
if(GAMEOVER)return;
if(cancleopt(pos,ID,1)){pos=player[pos].rplayer;continue;}
int cardid=player[pos].findcard('K');
if(~cardid)
player[pos].drewcard(cardid);
else {
player[pos].life--;
if(player[pos].identity=='M')if(surfaceidentity[ID]!=player[ID].identity)surfaceidentity[ID]='M';
if(player[pos].life<=0)player[pos].dead(player[ID]);
}
pos=player[pos].rplayer;
}
}
void arrow(int ID){
int pos=player[ID].rplayer;
while(pos!=ID){
if(GAMEOVER)return;
if(cancleopt(pos,ID,1)){pos=player[pos].rplayer;continue;}
int cardid=player[pos].findcard('D');
if(~cardid)
player[pos].drewcard(cardid);
else {
player[pos].life--;
if(player[pos].identity=='M')if(surfaceidentity[ID]!=player[ID].identity)surfaceidentity[ID]='M';
if(player[pos].life<=0)player[pos].dead(player[ID]);
}
pos=player[pos].rplayer;
}
}
void duel(int ID1,int ID2){
if(ID1!=1)surfaceidentity[ID1]=player[ID1].identity;
if(cancleopt(ID2,ID1,1))return;
if(player[ID2].identity=='Z'&&player[ID1].identity=='M'){
player[ID2].life--;
if(player[ID2].life<=0)player[ID2].dead(player[ID1]);
return;
}
int atk=ID1,dfn=ID2;
while(true){
swap(atk,dfn);
int cardid=player[atk].findcard('K');
if(~cardid)
player[atk].drewcard(cardid);
else break;
}
player[atk].life--;
if(player[atk].life<=0)player[atk].dead(player[dfn]);
}
//"main
inline void playing(){
int pos=1;
while(!GAMEOVER){
player[pos].getcard();player[pos].getcard();
player[pos].killtime=player[pos].equipment=='Z'?INF:1;
player[pos].MYTERM();
pos=player[pos].rplayer;
}
}
inline void init(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
player[i].playerID=i;
player[i].life=4;
player[i].lplayer=i-1,player[i].rplayer=i+1;
player[i].identity=getch();
if(player[i].identity=='F')Fcnt++;
for(int p=1;p<=4;p++){cont=0;player[i].getcard();}
}
player[1].lplayer=n,player[n].rplayer=1;
surfaceidentity[1]='Z';
}
int main()
{
init();cont=0;
playing();
for(int i=1;i<=n;i++) player[i].print();
}