[SDOI2010]猪国杀 解题报告

来源:互联网 发布:江苏11选5遗漏数据 编辑:程序博客网 时间:2024/05/21 10:48

这道题作为一道省选题,质量真是差到了极点!!强烈建议千万不要去做!


首先,这题意与数据不合,而样例怎么看都是错的,反猪明明有6张无懈!

题意与数据之龃龉:

①题目中n<=5,而实际上n<=10.

②题目中明确指出不会出现牌不够用的情况,而实际上你需要不断地抽最后一张牌。

也就是说,如果你按照题目要求写的话,你的最终得分将是:30分。。。(←_←这种题考场上能有人A才怪。)

而如果你RP爆发把数组开到10,那么你就能拿90分。。

我写的时候没有考虑到的地方:

①装诸葛连弩可能导致前面出杀。

②与他人决斗可能导致自己死亡,此时应及时中止出牌阶段!!←←←←此处最大坑点。

③反猪的决斗永远是献给主猪的(而不是什么逆时针第一个。。)。

④题目中的距离与平常意义上的距离不一样!是逆时针旋转的距离!


犯的一些SB错误:

①把>0写成>9.

②把pig[j].id<0写成j<0.

③企图用break退出switch的外层循环(实际上只能退switch,而如果是if的话这么做是可以退到循环的)。

代码(循题面拿30分):

#include<iostream>using namespace std;#include<cstdio>#include<cstring>#include<cstdlib>#include<cmath>#include<algorithm>#include<string>#include<map>struct LS{int data;LS * pred,* succ; }pl[5000];int tot;struct PS{int blood,id;//-3:跳了的反;-2:没跳的反;-1:就是反的类反;0:死猪;1:其实是忠的类反;2:没跳的忠;3:跳了的忠;4:主公 bool zhuge;//判断是否装备诸葛 LS begin[9],end[9];}pig[5];int pred[5],next[5];//猪们的链表 int heap[2000],m,n;//保存牌堆什么的。 int fsum;//保存反猪的数量 map<int,char> revf;map<char,int> f;//映射们 bool flag;//是否有人又跳了。 inline char gt(){//读取字符 char c=getchar();while(c<'A'||c>'Z')c=getchar();return c;}inline void got(int i,int pai){//猪i获得了牌paipl[tot]=(LS){pai,pig[i].end[0].pred,pig[i].end};pig[i].end[0].pred->succ=pl+tot,pig[i].end[0].pred=pl+tot++;pl[tot]=(LS){pai,pig[i].end[pai].pred,pig[i].end+pai};pig[i].end[pai].pred->succ=pl+tot,pig[i].end[pai].pred=pl+tot++;}inline void del(int i){//弃置牌i pl[i].pred->succ=pl[i].succ;pl[i].succ->pred=pl[i].pred;pl[i^1].pred->succ=pl[i^1].succ;pl[i^1].succ->pred=pl[i^1].pred;}inline void out(){//输出for(int i=0;i<n;++i){if(pig[i].blood)for(LS * j=pig[i].begin[0].succ;j!=pig[i].end;j=j->succ){putchar(revf[j->data]);if(j->succ!=pig[i].end)putchar(' ');}else printf("DEAD");putchar('\n');}}inline bool hate(int i,int j){//判断pig i是否讨厌pig jreturn pig[i].id==4&&abs(pig[j].id)==1||pig[i].id>0&&pig[j].id==-3||pig[i].id<0&&pig[j].id>=3;}inline void attack(int i,int j){//j受到来自i的一点伤害 if(--pig[j].blood==0){if(pig[j].begin[1].succ==pig[j].end+1){//判断j是否会死 //从链表中将其删除 next[pred[j]]=next[j];pred[next[j]]=pred[j];flag=1;//判断j的身份if(pig[j].id<0)--fsum;//判断游戏是否结束if(j*fsum==0){if(j)printf("MP");else printf("FP");putchar('\n');out();exit(0);}//判断是否存在奖励/惩罚if(pig[j].id>0&&i==0){pig[0].zhuge=0;for(int k=9;k--;){pig[0].begin[k].succ=pig[0].end+k;pig[0].end[k].pred=pig[0].begin+k;}}else if(pig[j].id<0)for(j=3;j--;)got(i,heap[--m]);}else{del(pig[j].begin[1].succ-pl);++pig[j].blood;}}}inline bool require(int i,int j,int p){//pig i向pig j请求一张p,否则pig i将向pig j造成1点伤害 if(pig[j].begin[p].succ==pig[j].end+p){attack(i,j);return 0;}else{del(pig[j].begin[p].succ-pl);return 1;}} inline void update(int i){//i跳了 if(pig[i].id>0&&pig[i].id<3)pig[i].id=3,flag=1;else if(pig[i].id<0&&pig[i].id>-3)pig[i].id=-3,flag=1;}inline bool find(int i,int flag){//从i开始,寻找身份为flag的猪打出无懈可击;同时认为其献殷勤/表敌意,跳反/忠 if(abs(flag)<3)return 0;if(pig[i].id*flag>0&&pig[i].begin[7].succ!=pig[i].end+7){del(pig[i].begin[7].succ-pl);update(i);return !find(i,-flag);}for(int j=next[i];j!=i;j=next[j])if(pig[j].id*flag>0&&pig[j].begin[7].succ!=pig[j].end+7){del(pig[j].begin[7].succ-pl);update(j);return !find(j,-flag);} return 0;}inline void req(int i,int p){//pig i向所有人请求p int blood=pig[0].blood;for(int j=next[i];j!=i;j=next[j])if(!find(i,pig[j].id))require(i,j,p);if(pig[0].blood!=blood&&abs(pig[i].id)==2){flag=1;pig[i].id/=2;}}int main(){int i,j;scanf("%d%d",&n,&m);//预处理//映射 f['P']=1,f['K']=2,f['D']=3,f['F']=4,f['N']=5,f['W']=6,f['J']=7,f['Z']=8;revf[1]='P',revf[2]='K',revf[3]='D',revf[4]='F',revf[5]='N',revf[6]='W',revf[7]='J',revf[8]='Z';//预处理单向链表,指向下一个还活着的猪。 for(i=n;--i;)next[i-1]=i,pred[i]=i-1;next[n-1]=0,pred[0]=n-1;//预处理猪们的牌表和血量。 for(i=n;i--;){pig[i].blood=4;for(j=9;j--;)pig[i].begin[j].succ=pig[i].end+j,pig[i].end[j].pred=pig[i].begin+j;}//Readfor(i=0;i<n;++i){switch(gt()){case 'M':pig[i].id=4;break;case 'Z':pig[i].id=2;break;case 'F':pig[i].id=-2;++fsum;}gt();for(j=4;j;--j)got(i,f[gt()]);}for(i=m;i--;)heap[i]=f[gt()];//如果没有反if(fsum==0){printf("MP\n");out();return 0;}//WorkLS * ptr;bool notyet;//当前回合是否出过杀。int fuck1,fuck2;//即将被表敌意的猪 for(i=0;;i=next[i]){//预处理notyet=1; fuck1=hate(i,next[i])?next[i]:-1;if(pig[i].id<0)fuck2=0;else{fuck2=next[i];while(fuck2!=i&&!hate(i,fuck2))fuck2=next[fuck2];}//摸牌 for(j=2;j--;)got(i,heap[--m]);//出牌for(ptr=pig[i].begin[0].succ;pig[i].blood&&ptr!=pig[i].end;ptr=ptr->succ){switch(ptr->data){case 1:if(pig[i].blood<4){del(ptr-pl);++pig[i].blood;}break;case 2:if(notyet|pig[i].zhuge&&fuck1+1){update(i);del(ptr-pl);notyet=0;require(i,fuck1,3);}break;case 8:del(ptr-pl);if(pig[i].zhuge==0){pig[i].zhuge=1;flag=1;}break;case 4:if(fuck2!=i){del(ptr-pl);update(i);if(!find(i,pig[fuck2].id)){if(i==0&&pig[fuck2].id>0)attack(i,fuck2);elsewhile(1){if(!require(i,fuck2,2))break;if(!require(fuck2,i,2))break;}}}break;case 5:del(ptr-pl);req(i,2);break;case 6:del(ptr-pl);req(i,3);break;}if(flag){flag=0;fuck1=hate(i,next[i])?next[i]:-1;if(pig[i].id<0)fuck2=0;else{fuck2=next[i];while(fuck2!=i&&!hate(i,fuck2))fuck2=next[fuck2];}ptr=pig[i].begin;}} }}

代码(AC):

#include<iostream>using namespace std;#include<cstdio>#include<cstring>#include<cstdlib>#include<cmath>#include<algorithm>#include<string>#include<map>struct LS{int data;LS * pred,* succ; }pl[1000000];int tot;struct PS{int blood,id;//-3:跳了的反;-2:没跳的反;-1:就是反的类反;0:死猪;1:其实是忠的类反;2:没跳的忠;3:跳了的忠;4:主公 bool zhuge;//判断是否装备诸葛 LS begin[9],end[9];}pig[50];int pred[50],next[50];//猪们的链表 int heap[10000],m,n;//保存牌堆什么的。 int fsum;//保存反猪的数量 map<int,char> revf;map<char,int> f;//映射们 bool flag;//是否有人又跳了。 inline char gt(){//读取字符 char c=getchar();while(c<'A'||c>'Z')c=getchar();return c;}inline void got(int i,int pai){//猪i获得了牌paipl[tot]=(LS){pai,pig[i].end[0].pred,pig[i].end};pig[i].end[0].pred->succ=pl+tot,pig[i].end[0].pred=pl+tot++;pl[tot]=(LS){pai,pig[i].end[pai].pred,pig[i].end+pai};pig[i].end[pai].pred->succ=pl+tot,pig[i].end[pai].pred=pl+tot++;}inline void del(int i){//弃置牌i pl[i].pred->succ=pl[i].succ;pl[i].succ->pred=pl[i].pred;pl[i^1].pred->succ=pl[i^1].succ;pl[i^1].succ->pred=pl[i^1].pred;}inline void out(){//输出for(int i=0;i<n;++i){if(pig[i].blood)for(LS * j=pig[i].begin[0].succ;j!=pig[i].end;j=j->succ){putchar(revf[j->data]);if(j->succ!=pig[i].end)putchar(' ');}else printf("DEAD");putchar('\n');}}inline bool hate(int i,int j){//判断pig i是否讨厌pig jreturn pig[i].id==4&&abs(pig[j].id)==1||pig[i].id>0&&pig[j].id==-3||pig[i].id<0&&pig[j].id>=3;}inline void attack(int i,int j){//j受到来自i的一点伤害 if(--pig[j].blood==0){if(pig[j].begin[1].succ==pig[j].end+1){//判断j是否会死 //从链表中将其删除 next[pred[j]]=next[j];pred[next[j]]=pred[j];flag=1;//判断j的身份if(pig[j].id<0)--fsum;//判断游戏是否结束if(j*fsum==0){if(j)printf("MP");else printf("FP");putchar('\n');out();exit(0);}//判断是否存在奖励/惩罚if(pig[j].id>0&&i==0){pig[0].zhuge=0;for(int k=9;k--;){pig[0].begin[k].succ=pig[0].end+k;pig[0].end[k].pred=pig[0].begin+k;}}else if(pig[j].id<0)for(j=3;j--;)got(i,heap[m?--m:0]);}else{del(pig[j].begin[1].succ-pl);++pig[j].blood;}}}inline bool require(int i,int j,int p){//pig i向pig j请求一张p,否则pig i将向pig j造成1点伤害 if(pig[j].begin[p].succ==pig[j].end+p){attack(i,j);return 0;}else{del(pig[j].begin[p].succ-pl);return 1;}} inline void update(int i){//i跳了 if(pig[i].id>0&&pig[i].id<3)pig[i].id=3,flag=1;else if(pig[i].id<0&&pig[i].id>-3)pig[i].id=-3,flag=1;}inline bool find(int i,int flag){//从i开始,寻找身份为flag的猪打出无懈可击;同时认为其献殷勤/表敌意,跳反/忠 if(abs(flag)<3)return 0;if(pig[i].id*flag>0&&pig[i].begin[7].succ!=pig[i].end+7){del(pig[i].begin[7].succ-pl);update(i);return !find(i,-flag);}for(int j=next[i];j!=i;j=next[j])if(pig[j].id*flag>0&&pig[j].begin[7].succ!=pig[j].end+7){del(pig[j].begin[7].succ-pl);update(j);return !find(j,-flag);} return 0;}inline void req(int i,int p){//pig i向所有人请求p int blood=pig[0].blood;for(int j=next[i];j!=i;j=next[j])if(!find(i,pig[j].id))require(i,j,p);if(pig[0].blood!=blood&&abs(pig[i].id)==2){flag=1;pig[i].id/=2;}}int main(){int i,j;scanf("%d%d",&n,&m);//预处理//映射 f['P']=1,f['K']=2,f['D']=3,f['F']=4,f['N']=5,f['W']=6,f['J']=7,f['Z']=8;revf[1]='P',revf[2]='K',revf[3]='D',revf[4]='F',revf[5]='N',revf[6]='W',revf[7]='J',revf[8]='Z';//预处理单向链表,指向下一个还活着的猪。 for(i=n;--i;)next[i-1]=i,pred[i]=i-1;next[n-1]=0,pred[0]=n-1;//预处理猪们的牌表和血量。 for(i=n;i--;){pig[i].blood=4;for(j=9;j--;)pig[i].begin[j].succ=pig[i].end+j,pig[i].end[j].pred=pig[i].begin+j;}//Readfor(i=0;i<n;++i){switch(gt()){case 'M':pig[i].id=4;break;case 'Z':pig[i].id=2;break;case 'F':pig[i].id=-2;++fsum;}gt();for(j=4;j;--j)got(i,f[gt()]);}for(i=m;i--;)heap[i]=f[gt()];//如果没有反if(fsum==0){printf("MP\n");out();return 0;}//WorkLS * ptr;bool notyet;//当前回合是否出过杀。int fuck1,fuck2;//即将被表敌意的猪 for(i=0;;i=next[i]){//预处理notyet=1; fuck1=hate(i,next[i])?next[i]:-1;if(pig[i].id<0)fuck2=0;else{fuck2=next[i];while(fuck2!=i&&!hate(i,fuck2))fuck2=next[fuck2];}//摸牌 for(j=2;j--;)got(i,heap[m?--m:0]);//出牌for(ptr=pig[i].begin[0].succ;pig[i].blood&&ptr!=pig[i].end;ptr=ptr->succ){switch(ptr->data){case 1:if(pig[i].blood<4){del(ptr-pl);++pig[i].blood;}break;case 2:if(notyet|pig[i].zhuge&&fuck1+1){update(i);del(ptr-pl);notyet=0;require(i,fuck1,3);}break;case 8:del(ptr-pl);if(pig[i].zhuge==0){pig[i].zhuge=1;flag=1;}break;case 4:if(fuck2!=i){del(ptr-pl);update(i);if(!find(i,pig[fuck2].id)){if(i==0&&pig[fuck2].id>0)attack(i,fuck2);elsewhile(1){if(!require(i,fuck2,2))break;if(!require(fuck2,i,2))break;}}}break;case 5:del(ptr-pl);req(i,2);break;case 6:del(ptr-pl);req(i,3);break;}if(flag){flag=0;fuck1=hate(i,next[i])?next[i]:-1;if(pig[i].id<0)fuck2=0;else{fuck2=next[i];while(fuck2!=i&&!hate(i,fuck2))fuck2=next[fuck2];}ptr=pig[i].begin;}} }}


1 0
原创粉丝点击