模拟

宏定义预处理器,实现简化版预处理器,不包含函数,字符ASCII码范围32~126.

namespace JRC{
    string solve(string s){
        string re="";
        for(int i=0,j=0;i<s.size();i+=j){/*每次往后跳一个字符串的长度*/
            for(j=0;i+j<s.size()&&isalnum(s[i+j])||s[i+j]=='_';j++);
            if(j){
                string tmp=s.substr(i,j);/*截取当前串*/
                if(def.count(tmp)&&!def[tmp].second){/*被定义且未处于展开状态*/
                    def[tmp].second=1;/*开始展开*/
                    re+=solve(def[tmp].first);/*递归展开*/
                    def[tmp].second=0;/*展开结束*/
                }
                else re+=tmp;
            }
            else re+=s[i++];
        }
        return re;
    }
    inline void main(){
        cin>>n;
        for(int i=0;i<=n;i++)getline(cin,s[i]);
        for(int i=1;i<=n;i++){
            if(s[i][0]=='#'){
                if(s[i][1]=='d'){
                    int pos=s[i].find_first_of(' ',8);/*找到第二个空格的位置*/
                    string name=s[i].substr(8,pos-8)/*截取定义名*/,to=s[i].substr(pos+1);/*剩下的全部是转换成的文本*/
                    def[name]={to,0};
                }
                else def.erase(s[i].substr(7));
                cout<<'\n';
            }
            else cout<<solve(s[i])<<'\n';
        }
    }
}

儒略日。数学找规律。

// 2299160:
// int ans=0;
// for(int i=-4712;i<1582;i++)ans+=365+(i%4==0);
// for(int i=1;i<=9;i++){
//     if(i==4||i==6||i==9||i==11)ans+=30;
//     else if(i==2)ans+=28;
//     else ans+=31;
// }
// ans+=4
#define int long long
const int N=146097;/*格里高利历一年的天数*/
int y[N],m[N],d[N];
namespace JRC{
    inline int mod(int y,int m){/*格里高利历在y年m月对应的天数*/
        if(m==2)return(y%400==0||(y%4==0&&y%100))?29:28;
        return (m==4||m==6||m==9||m==11)?30:31;
    }
    inline void main(){
        m[0]=d[0]=1;
        for(int i=1;i<N;i++){
            d[i]=d[i-1]+1;
            m[i]=m[i-1];
            y[i]=y[i-1];
            if(d[i]>mod(y[i],m[i]))d[i]=1,m[i]++;
            if(m[i]>12)m[i]=1,y[i]++;
        }
        int q;
        cin>>q;
        while(q--){
            int n,t;
            cin>>n;
            if(n>2299160){/*公元1582年10月4日是第2299160天,之后是格里高利历*/
                n-=2159351;/*第2159351天对应公元1199年12月25日*/
                t=n/N*400+1200;
                n%=N;
            }
            else{/*第一天即公元前4713年1月2日*/
                t=n/1461*4-4712;
                n%=1461;/*儒略历4年的天数*/
            }
            if(t+y[n]>0)cout<<d[n]<<' '<<m[n]<<' '<<t+y[n]<<'\n';
            else cout<<d[n]<<' '<<m[n]<<' '<<1-t-y[n]<<" BC\n";
        }
    }
}

斗地主,3<4<5<6<7<8<9<10<J<Q<K<A<2<小王<大王,分别最少需要多少次出牌可以将它们打光,出牌包括双王,四张为炸弹,单牌,对牌,三牌,三带一,三带一对,单顺子,双顺子,三顺子,四带两张单牌,四带两对牌,其中顺子不包含2和大小王。优先顺子,之后几带几,最后是三牌,搜索加模拟。

namespace JSY{
    void dfs(int x){
        if(x>=ans)return;/*只有顺子不带2和王*/
        for(int i=3,k=0;i<=14;i++){
            if(cnt[i]<1){/*单顺子*/
                k=0;
                continue;
            }
            k++;
            if(k<5)continue;
            for(int j=i;j>=i-k+1;j--)cnt[j]--;
            dfs(x+1);
            for(int j=i;j>=i-k+1;j--)cnt[j]++;
        }
        for(int i=3,k=0;i<=14;i++){
            if(cnt[i]<2){/*双顺子*/
                k=0;
                continue;
            }
            k++;
            if(k<3)continue;
            for(int j=i;j>=i-k+1;j--)cnt[j]-=2;
            dfs(x+1);
            for(int j=i;j>=i-k+1;j--)cnt[j]+=2;
        }
        for(int i=3,k=0;i<=14;i++){
            if(cnt[i]<3){/*三顺子*/
                k=0;
                continue;
            }
            k++;
            if(k<2)continue;
            for(int j=i;j>=i-k+1;j--)cnt[j]-=3;
            dfs(x+1);
            for(int j=i;j>=i-k+1;j--)cnt[j]+=3;
        }
        for(int i=2;i<=14;i++){
            if(cnt[i]<3)continue;/*判断可以带牌*/
            if(cnt[i]<4){/*用三张i去带别人*/
                cnt[i]-=3;
                for(int j=2;j<=15;j++){/*判断三带一*/
                    if(i==j||cnt[j]<1)continue;
                    cnt[j]--;/*j被带走了一张*/
                    dfs(x+1);
                    cnt[j]++;/*回溯*/
                    if(cnt[j]<2)continue;/*判断可以三带一对*/
                    cnt[j]-=2;/*j被带走了一对*/
                    dfs(x+1);
                    cnt[j]+=2;/*回溯*/
                }
                cnt[i]+=3;
            }
            else{
                cnt[i]-=3;/*优先三张i去带别人*/
                for(int j=2;j<=15;j++){
                    if(i==j||cnt[j]<1)continue;
                    cnt[j]--;
                    dfs(x+1);
                    cnt[j]++;
                    if(cnt[j]<2)continue;
                    cnt[j]-=2;
                    dfs(x+1);
                    cnt[j]+=2;
                }
                cnt[i]+=3;
                cnt[i]-=4;/*四张i去带别人,四带两单或两对*/
                for(int j=2;j<=15;j++){
                    if(i==j||cnt[j]<1)continue;
                    cnt[j]--;/*找到一单*/
                    for(int k=j+1;k<=15;k++){
                        if(i==k||cnt[k]<1)continue;
                        cnt[k]--;/*找到二单*/
                        dfs(x+1);
                        cnt[k]++;
                    }
                    cnt[j]++;
                }
                for(int j=2;j<=14;j++){
                    if(i==j||cnt[j]<2)continue;
                    cnt[j]-=2;/*找到一对*/
                    for(int k=j+1;k<=14;k++){
                        if(j==k||i==k||cnt[k]<2)continue;
                        cnt[k]-=2;/*找到二对*/
                        dfs(x+1);
                        cnt[k]+=2;
                    }
                    cnt[j]+=2;
                }
                cnt[i]+=4;
            }
        }
        for(int i=2;i<=15;i++)if(cnt[i])x++;
        ans=min(ans,x);
    }
    inline void main(){
        int t;cin>>t>>n;
        while(t--){
            ans=66;
            memset(cnt,0,sizeof(cnt));
            for(int i=1;i<=n;i++){
                int x,y;
                cin>>x>>y;
                switch(x){
                    case 1:cnt[14]++;break;
                    case 0:cnt[15]++;break;
                    default:cnt[x]++;break;
                }
            }
            dfs(0);
            cout<<ans<<'\n';
        }
    }
}

猪国杀。无懈可击要递归处理,对于每张牌如果能出,要先删掉再进行相应的操作。

#include<cstdio>
#include<iostream>
#include<queue>
#include<vector>
using namespace std;
const int N=666;
int n;
int m;
int maxhp=4;//血量上限
int running=1;//游戏未结束
int tot;//存活者数量
int cnt;//反猪数量
struct Player{
    string identity;//身份
    int hp=maxhp;//血量
    int nxt=0;//下一个人
    int pre=0;//上一个人
    bool showidentity=0;//跳身份
    bool similar=0;//类反猪
    bool equip=0;//装备
    bool dead=0;//死亡
    vector<string>card;//手牌
    inline void clear(){
        identity.clear();
        card.clear();
        hp=maxhp;
        nxt=0;
        pre=0;
        showidentity=0;
        similar=0;
        dead=0;
    }
    inline void get(string s){//增加手牌
        card.push_back(s);
    }
    inline bool have(string s){//是否有特定手牌
        for(auto it=card.begin();it!=card.end();it++){
            if(*it==s){
                return 1;
            }
        }
        return 0;
    }
    inline void erase(string s){//弃置特定手牌
        for(auto it=card.begin();it!=card.end();it++){
            if(*it==s){
                card.erase(it);
                return;
            }
        }
    }
    inline vector<string>::iterator erase(vector<string>::iterator it){
        it=card.erase(it);
        return --it;
    }
    inline void show(){
        cout<<"身份:"<<identity<<",血量:"<<hp<<",跳:"<<showidentity<<",类:"<<similar<<",装备:"<<equip<<",死亡:"<<dead<<'\n';
        cout<<"手牌:";
        for(auto x:card)cout<<x<<' ';
        cout<<'\n';
    }
}player[N];
struct Card{
    queue<string>card;
    inline void clear(){
        while(!card.empty()){
            card.pop();
        }
    }
    inline void push(string s){//牌堆增加牌
        card.push(s);
    }
    inline string get(){//从牌堆取牌
        if(card.size()==1){
            return card.front();
        }
        string s=card.front();
        card.pop();
        return s;
    }
}card;
inline void showidentity(int id){
    if(player[id].identity=="MP"){
        cout<<"主猪";
    }
    else if(player[id].identity=="ZP"){
        cout<<"忠猪";
    }
    else if(player[id].identity=="FP"){
        cout<<"反猪";
    }
}
inline void showcard(string s){
    if(s=="P"){
        cout<<"【桃】";
    }
    else if(s=="K"){
        cout<<"【杀】";
    }
    else if(s=="D"){
        cout<<"【闪】";
    }   
    else if(s=="F"){
        cout<<"【决斗】";
    }
    else if(s=="N"){
        cout<<"【南猪入侵】";
    }
    else if(s=="W"){
        cout<<"【万箭齐发】";
    }
    else if(s=="J"){
        cout<<"【无懈可击】";
    }
    else if(s=="Z"){
        cout<<"【猪哥连弩】";
    }
}
inline void use(int id,string s,int to=0){
    if(!to){
        showidentity(id);
        cout<<id<<"使用了";
        showcard(s);
        cout<<'\n';
    }
    else{
        showidentity(id);
        cout<<id<<"对";
        showidentity(to);
        cout<<to<<"使用了";
        showcard(s);
        cout<<'\n';
    }
}
inline void getcard(int id,int n=2){//id取n张牌
    for(int i=1;i<=n;i++){
        player[id].get(card.get());
    }
}
inline void init(){
    cin>>n>>m;
    tot=n;
    card.clear();
    for(int i=1;i<=n;i++){
        player[i].clear();
        player[i].nxt=i+1;
        player[i].pre=i-1;
        string s;
        cin>>s;
        player[i].identity=s;
        if(s=="FP"){
            cnt++;
        }
        for(int j=1;j<=4;j++){
            cin>>s;
            player[i].get(s);
        }
    }
    player[1].showidentity=1;
    player[1].pre=n;
    player[n].nxt=1;
    running=1;
    for(int i=1;i<=m;i++){
        string s;
        cin>>s;
        card.push(s);
    }
}
inline bool same(int x,int y){//同一阵营
    if(player[x].identity==player[y].identity){//相同类型
        return 1;
    }
    if(player[x].identity=="MP"&&player[y].identity=="ZP"){//主猪与忠猪
        return 1;
    }
    if(player[x].identity=="ZP"&&player[y].identity=="MP"){//忠猪与主猪
        return 1;
    }
    return 0;
}
inline bool bad(int x,int y){//表敌意
    if(!player[y].showidentity){//未表露身份
        if(player[x].identity=="MP"&&player[y].similar){//主猪对类反猪
            return 1;
        }
        return 0;//无法表露敌意
    }
    return !same(x,y);
}
inline int bad(int id){
    if(player[id].identity=="FP"){//反猪对主猪表敌意
        return 1;
    }
    int to=player[id].nxt;
    while(id!=to){
        if(bad(id,to)){
            return to;
        }
        to=player[to].nxt;
    }
    return 0;
}
inline bool good(int x,int y){
    if(!player[y].showidentity){//不会对未表露身份的角色献殷勤
        return 0;
    }
    return same(x,y);
}
inline void Peach(int id){//使用【桃】
    // use(id,"P");
    player[id].hp++;
}
inline void dead(int from,int to){
    if(player[to].have("P")){//濒死者用【桃】回血
        Peach(to);
        player[to].erase("P");
        return;
    }
    player[to].dead=1;
    tot--;
    if(player[to].identity=="MP"){
        running=0;//主猪死亡,游戏结束
        return;
    }
    else if(player[to].identity=="FP"){
        cnt--;
        if(!cnt){
            running=0;
            return;
        }
    }
    player[player[to].pre].nxt=player[to].nxt;
    player[player[to].nxt].pre=player[to].pre;
    if(player[to].identity=="FP"){//杀死反猪摸三张
        getcard(from,3);
    }
    else if(player[from].identity=="MP"&&player[to].identity=="ZP"){//主猪杀死忠猪
        player[from].card.clear();//弃置手牌
        player[from].equip=0;//弃置装备
    }
}
inline void hurt(int from,int to){
    player[to].hp--;
    if(player[to].identity=="MP"){//攻击主猪者被视为类反猪
        player[from].similar=1;
    }
    if(!player[to].hp)dead(from,to);
}
inline void Equipment(int id){//使用【猪哥连弩】
    player[id].equip=1;
}
inline void Kill(int from,int to){//使用【杀】
    player[from].showidentity=1;//对敌方表敌意,那么自己表露了身份
    if(player[to].have("D")){//敌方有【闪】
        // use(to,"D");
        player[to].erase("D");
    }
    else{
        hurt(from,to);//造成伤害
    }
}
bool Flawless(int from,int to,int op){//【无懈可击】递归
    int k=tot;
    while(k--){
        if(player[to].have("J")){
            if(op&&good(to,from)){//op=1表示需要对from献殷勤,from是收到伤害的一方,需要无懈可击的支援
                // use(to,"J",from);
                player[to].showidentity=1;
                player[to].erase("J");
                return !Flawless(from,player[to].nxt,op^1);//需要对from表敌意的人表敌意失败,那么自己便成功了
            }
            else if(!op&&bad(to,from)){//op=0表示需要对from表敌意
                // use(to,"J",from);
                player[to].showidentity=1;
                player[to].erase("J");
                return !Flawless(from,player[to].nxt,op^1);
            }
        }
        to=player[to].nxt;
    }
    return 0;
}
inline void Duel(int from,int to){//【决斗】
    player[from].showidentity=1;
    if(Flawless(to,from,1))return;
    if(player[from].identity=="MP"&&player[to].identity=="ZP"){//忠猪不对主猪的决斗出杀
        hurt(from,to);
        return;
    }
    while(1){
        if(player[to].have("K")){
            // use(to,"K");
            player[to].erase("K");
        }
        else{
            hurt(from,to);
            break;
        }
        if(player[from].have("K")){
            // use(to,"K");
            player[from].erase("K");
        }
        else{
            hurt(to,from);
            break;
        }
    }
}
inline void BarbarianBreakout(int id){//【南猪入侵】
    int to=player[id].nxt;
    while(id!=to&&running){
        if(Flawless(to,id,1)){
            to=player[to].nxt;
            continue;
        }
        if(player[to].have("K")){
            player[to].erase("K");
            to=player[to].nxt;
            continue;
        }
        hurt(id,to);
        to=player[to].nxt;
    }
}
inline void ThousandSpear(int id){//【万箭齐发】
    int to=player[id].nxt;
    while(id!=to&&running){
        if(Flawless(to,id,1)){
            to=player[to].nxt;
            continue;
        }
        if(player[to].have("D")){
            player[to].erase("D");
            to=player[to].nxt;
            continue;
        }
        hurt(id,to);
        to=player[to].nxt;
    }
}
inline void play(){
    int id=1;//本回合玩家编号
    bool usekill=0;//是否使用过杀
    bool usecard=0;//是否出过牌
    while(running){
        getcard(id,2);
        usekill=0;
        while(!player[id].dead&&running){
            usecard=0;
            for(auto it=player[id].card.begin();it!=player[id].card.end();it++){
                if(player[id].dead||!running)break;
                if(*it=="P"){
                    if(player[id].hp<maxhp){
                        usecard=1;
                        Peach(id);
                        player[id].erase(it);
                    }
                }
                else if(*it=="Z"){
                    usecard=1;
                    Equipment(id);
                    usekill=0;//可以再次使用杀
                    player[id].erase(it);
                }
                else if(*it=="K"){
                    if(usekill)continue;
                    if(bad(id,player[id].nxt)){
                        usecard=1;
                        if(!player[id].equip)usekill=1;
                        player[id].erase(it);
                        Kill(id,player[id].nxt);
                    }
                }
                else if(*it=="F"){
                    int to=bad(id);
                    if(!to)continue;
                    usecard=1;
                    player[id].erase(it);
                    Duel(id,to);
                }
                else if(*it=="N"){
                    usecard=1;
                    player[id].erase(it);
                    BarbarianBreakout(id);
                }
                else if(*it=="W"){
                    usecard=1;
                    player[id].erase(it);//顺序相关?
                    ThousandSpear(id);
                }
                if(usecard)break;
            }
            if(!usecard)break;
        }
        id=player[id].nxt;
    }
}
int main(){
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    init();
    play();
    if(!cnt){
        cout<<"MP\n";
    }
    else{
        cout<<"FP\n";
    }
    for(int i=1;i<=n;i++){
        if(player[i].dead){
            cout<<"DEAD\n";
        }
        else{
            for(auto x:player[i].card){
                cout<<x<<' ';
            }
            cout<<'\n';
        }
    }
    return 0;
}

压行版本。

#include<bits/stdc++.h>
using namespace std;
const int N=666;
int n,m,maxhp=4,tot,cnt;bool running;
struct Player{
    string identity;int hp=maxhp,nxt,pre,showidentity,similar,equip,dead;vector<string>card;
    inline bool operator==(const Player&x){return (identity==x.identity)||(identity=="MP"&&x.identity=="ZP")||(identity=="ZP"&&x.identity=="MP");}
    inline bool operator!=(const Player&x){return ((*this)==x)==false;}
    inline void operator+=(string s){card.push_back(s);}
    inline void operator~(){identity.clear();card.clear();hp=maxhp;nxt=pre=showidentity=similar=dead=false;}
    inline bool operator-(string s){for(auto x:card)if(x==s)return true;return false;}
    inline void operator-=(string s){for(auto it=card.begin();it!=card.end();it++)if(*it==s)return card.erase(it),void();}
}player[N];
struct Card{
    queue<string>card;
    inline void operator~(){while(!card.empty())card.pop();}
    inline void operator+=(string s){card.push(s);}
    inline string operator--(){if(card.size()==1)return card.front();string s=card.front();card.pop();return s;}
}card;
inline void getcard(int x,int n){while(n--)player[x]+=--card;}
inline bool good(int x,int y){return player[y].showidentity?player[x]==player[y]:false;}
inline bool bad(int x,int y){return player[y].showidentity?(player[x]!=player[y]):(player[x].identity=="MP"&&player[y].similar==true);}
inline void nxt(int&x){x=player[x].nxt;}
inline int findgoal(int x){if(player[x].identity=="FP")return 1;int y=player[x].nxt;while(x!=y){if(bad(x,y))return y;nxt(y);}return 0;}
inline void Peach(int x){player[x].hp++;}
inline void dead(int x,int y){
    if(player[y]-"P")return Peach(y),player[y]-="P",void();
    player[y].dead=true,tot--;
    if(player[y].identity=="MP"||(player[y].identity=="FP"&&--cnt==false))return running=false,void();
    player[player[y].pre].nxt=player[y].nxt,player[player[y].nxt].pre=player[y].pre,player[y].identity=="FP"?(getcard(x,3),0):((player[x].identity=="MP"&&player[y].identity=="ZP")?player[x].card.clear(),player[x].equip=false:0);
}
inline void hurt(int x,int y){player[y].hp--,player[x].similar=player[y].identity=="MP",(player[y].hp==false)?dead(x,y),0:0;}
inline void Equipment(int x){player[x].equip=true;}
inline void Kill(int x,int y){player[x].showidentity=true,player[y]-"D"?player[y]-="D":hurt(x,y);}
bool Flawless(int x,int y,bool f){for(int k=tot;k;k--,nxt(y))if(player[y]-"J"==true&&((f==true&&good(y,x))||(f==false&&bad(y,x))))return player[y].showidentity=true,player[y]-="J",Flawless(x,player[y].nxt,f^1)==false;return false;}
inline void Duel(int x,int y){
    player[x].showidentity=true;
    if(Flawless(y,x,true)==true)return;
    if(player[x].identity=="MP"&&player[y].identity=="ZP")return hurt(x,y),void();
    while(true){
        if(player[y]-"K")player[y]-="K";
        else{hurt(x,y);break;}
        if(player[x]-"K")player[x]-="K";
        else{hurt(y,x);break;}
    }
}
inline void BarbarianBreakout(int x){for(int y=player[x].nxt;x!=y&&running==true;nxt(y))(Flawless(y,x,true)||(player[y]-"K"&&(player[y]-="K",1)))?1:(hurt(x,y),1);}
inline void ThousandSpear(int x){for(int y=player[x].nxt;x!=y&&running==true;nxt(y))(Flawless(y,x,true)||(player[y]-"D"&&(player[y]-="D",1)))?1:(hurt(x,y),1);}
inline void init(){
    cin>>n>>m;tot=n;~card;string s;
    for(int i=1;i<=n;i++){
        ~player[i];player[i].nxt=i+1,player[i].pre=i-1;
        cin>>s;cnt+=s=="FP";player[i].identity=s;
        for(int j=1;j<=4;j++)cin>>s,player[i]+=s;
    }
    player[1].pre=n,player[n].nxt=1,player[1].showidentity=true;
    for(int i=1;i<=m;i++)cin>>s,card+=s;
    running=true;
}
inline void play(){
    int id=1,y;
    while(running){
        getcard(id,2);
        bool usekill=false;
        while(player[id].dead==false&&running){
            bool usecard=false;
            for(auto x:player[id].card){
                if(player[id].dead==true||running==false)break;
                if(x=="P"&&player[id].hp<maxhp)player[id]-="P",usecard=true,Peach(id);
                else if(x=="Z")player[id]-="Z",usecard=true,usekill=false,Equipment(id);
                else if(x=="K"&&usekill==false&&bad(id,player[id].nxt)!=false)player[id]-="K",usecard=true,usekill=player[id].equip^1,Kill(id,player[id].nxt);
                else if(x=="F"&&(y=findgoal(id))!=false)player[id]-="F",usecard=true,Duel(id,y);
                else if(x=="N")player[id]-="N",usecard=true,BarbarianBreakout(id);
                else if(x=="W")player[id]-="W",usecard=true,ThousandSpear(id);
                if(usecard==true)break;
            }
            if(usecard==false)break;
        }
        nxt(id);
    }
}
inline void print(){
    cout<<(cnt==false?"MP":"FP")<<'\n';
    for(int i=1;i<=n;i++){
        if(player[i].dead==true)cout<<"DEAD";
        else for(auto x:player[i].card)cout<<x<<' ';
        cout<<'\n';
    }
}
int main(){
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    init();
    play();
    print();
    return 0;
}

杀蚂蚁。用STL的list维护当前存活的蚂蚁。

#include<cstdio>
#include<iostream>
#include<list>
#include<cmath>
using namespace std;

const int N=22;
const double eps=1e-8;
int n;
int m;
int num;//炮塔数量
int damage;//炮塔伤害
int radius;//炮塔攻击半径
int endtime;//模拟时间
int tim;//当前时间
int tot;//出生的蚂蚁总数
int livetot;//当前存活的蚂蚁数量
int dx[4]={0,1,0,-1};//方向数组
int dy[4]={1,0,-1,0};
bool cakefly=false;//蛋糕被抢
struct Map{
    int information=0;//信息素含量
    bool use=false;//是否被占用
}mp[N][N];
struct Ant{
    int age=0;//年龄
    int level=0;//等级
    int hp=0;//血量
    int maxhp=0;//血量上限
    int x=0;//当前坐标
    int y=0;
    int px=0;//上一秒坐标
    int py=0;
    bool havecake=false;//背着蛋糕
};
list<Ant>ant;
struct Turret{
    int x;
    int y;
    double radius=0;//最小攻击半径
    bool havetarget=false;//是否有普通目标
    bool caketarget=false;//是否有优先目标
    list<Ant>::iterator target;//攻击目标
}turret[N];
inline void antborn(){//蚂蚁出生
    if(livetot>5||mp[0][0].use==true){//不足六只且洞口没有蚂蚁才诞生
        return;
    }
    tot++;
    livetot++;
    int level=(tot-1)/6+1;//等级
    int hp=4*pow(1.1,level);//初始血量及上限
    ant.push_back({0,level,hp,hp,0,0,0,0,false});
    mp[0][0].use=true;//出生后的蚂蚁占用洞口
}
inline void release(){//释放信息素
    for(auto x:ant){
        if(x.havecake==true){
            mp[x.x][x.y].information+=5;
        }
        else{
            mp[x.x][x.y].information+=2;
        }
    }
}
inline bool check(int x,int y){
    if(x<0||y<0||x>n||y>m||mp[x][y].use==true)return false;
    return true;
}
inline void antmove(){//蚂蚁移动
    for(auto&x:ant){
        int maxinformation=0,pos=0,cnt=0;
        for(int i=0;i<4;i++){
            int tx=x.x+dx[i],ty=x.y+dy[i];
            if(check(tx,ty)==true&&(x.px!=tx||x.py!=ty)){
                if(mp[tx][ty].information>maxinformation){//优先信息素最多
                    maxinformation=mp[tx][ty].information;
                    pos=i;
                    cnt=1;
                }
                else if(mp[tx][ty].information==maxinformation){//多个相同信息素
                    pos=i;
                    cnt++;
                }
            }
        }
        if(cnt==0){//无路可走
            x.px=x.x;
            x.py=x.y;
            continue;
        }
        if(cnt>1){
            for(int i=0;i<4;i++){
                int tx=x.x+dx[i],ty=x.y+dy[i];
                if(check(tx,ty)&&(x.px!=tx||x.py!=ty)&&mp[tx][ty].information==maxinformation){//从东开始找到第一个
                    pos=i;
                    break;
                }
            }
        }
        if((x.age+1)%5==0){//需要逆时针转向
            for(int i=0;i<4;i++){
                pos--;
                if(pos<0){
                    pos+=4;
                }
                int tx=x.x+dx[pos],ty=x.y+dy[pos];
                if(check(tx,ty)&&(x.px!=tx||x.py!=ty)){//找到第一个可以走的方向
                    break;
                }
            }
        }
        x.px=x.x;
        x.py=x.y;
        x.x+=dx[pos];
        x.y+=dy[pos];
        mp[x.px][x.py].use=false;//清空之前标记
        mp[x.x][x.y].use=true;//建立新标记
    }
}
inline void checkcake(){//检查蛋糕是否被抢
    if(cakefly==true){
        return;
    }
    for(auto&x:ant){
        if(x.x==n&&x.y==m){//蛋糕被抢
            x.havecake=true;
            cakefly=true;
            x.hp=min(x.hp+(int)(1.0*x.maxhp/2.0),x.maxhp);//更新血量
            break;
        }
    }
}
inline double getdis(double x,double y,double a,double b){
    return sqrt((x-a)*(x-a)+(y-b)*(y-b));
}
struct Vector{
    double x,y;
    const double pi=acos(-1);
    inline Vector(double a=0,double b=0){x=a,y=b;}
    inline friend Vector operator+(const Vector&a,const Vector&b){return Vector(a.x+b.x,a.y+b.y);}
    inline friend Vector operator-(const Vector&a,const Vector&b){return Vector(a.x-b.x,a.y-b.y);}
    inline friend Vector operator*(const Vector&a,const double&b){return Vector(a.x*b,a.y*b);}
    inline friend Vector operator/(const Vector&a,const double&b){return Vector(a.x/b,a.y/b);}
    inline friend double operator&(const Vector&a,const Vector&b){return a.x*b.y-a.y*b.x;}//叉积 
    inline friend double operator|(const Vector&a,const Vector&b){return a.x*b.x+a.y*b.y;}//点积
    inline double operator~()const{return sqrt(x*x+y*y);}//模长
    inline double operator!()const{return atan2(y,x);}//弧度*180/pi=度数
    inline double slope()const{return y/x;}
    inline int doublepos(double x)const{return (fabs(x)<eps)?0:((x<0)?-1:1);}
    inline Vector rotate(const double&a){return Vector(x*cos(a)-y*sin(a),x*sin(a)+y*cos(a));}
    inline double pointsegmentdis(const Vector&p,const Vector&a,const Vector&b){
        Vector v=b-a,v0=p-a,v1=p-b;
        if(doublepos(v|v0)<0)return ~v0;
        if(doublepos(v|v1)>0)return ~v1;
        return fabs((v&v0)/~v);
    }
};
inline void attack(){//炮塔攻击
    for(int i=1;i<=num;i++){//选定目标
        turret[i].havetarget=false;
        turret[i].caketarget=false;
        turret[i].radius=1e7;
        for(auto it=ant.begin();it!=ant.end();it++){
            double dis=getdis(it->x,it->y,turret[i].x,turret[i].y);
            if(dis<=radius+eps){//处于攻击范围之内
                turret[i].havetarget=true;//获得目标
                if(it->havecake==true){
                    turret[i].caketarget=true;//获得拥有蛋糕的目标
                    turret[i].target=it;
                }
                else if(dis<turret[i].radius&&turret[i].caketarget==false){//一个离得最近的目标且没有获得蛋糕的目标
                    turret[i].radius=dis;
                    turret[i].target=it;
                }
            }
            if(turret[i].caketarget==true){//有获得蛋糕的目标后break
                break;
            }
        }
    }
    for(int i=1;i<=num;i++){//进行攻击
        if(turret[i].havetarget==false){//没有表跳过
            continue;
        }
        if(turret[i].caketarget==false){//没有获得蛋糕的目标
            turret[i].target->hp-=damage;//近攻击离自己最近的目标
            continue;
        }
        Vector a(turret[i].target->x,turret[i].target->y),b(turret[i].x,turret[i].y);
        for(auto&x:ant){
            Vector p(x.x,x.y);
            if(p.pointsegmentdis(p,a,b)<=0.5+eps){//处于攻击范围之内,0.5是蚂蚁的半径
                x.hp-=damage;
            }
        }
    }
}
inline void clear(){//处理尸体
    for(auto it=ant.begin();it!=ant.end();it++){
        if(it->hp<0){
            if(it->havecake==true){//蛋糕归位
                cakefly=false;
            }
            mp[it->x][it->y].use=false;//清空标记
            it=ant.erase(it);
            it--;
            livetot--;
        }
    }
}
inline bool gameover(){//判断游戏结束
    for(auto x:ant){
        if(x.havecake==true&&x.x==0&&x.y==0){
            return true;
        }
    }
    return false;
}
inline void update(){//时间流逝
    for(int i=0;i<=n;i++){
        for(int j=0;j<=m;j++){
            if(mp[i][j].information){//信息素最少是0
                mp[i][j].information--;
            }
        }
    }
    for(auto&x:ant){//年龄长大
        x.age++;
    }
}
inline void init(){
    cin>>n>>m>>num>>damage>>radius;
    for(int i=1;i<=num;i++){
        int x,y;
        cin>>x>>y;
        turret[i].x=x;
        turret[i].y=y;
        mp[x][y].use=true;
    }
    cin>>endtime;
}
inline void play(){
    for(tim=1;tim<=endtime;tim++){
        antborn();
        release();
        antmove();
        checkcake();
        attack();
        clear();
        if(gameover()){
            break;
        }
        update();
    }
}
inline void print(){
    if(tim==endtime+1){
        cout<<"The game is going on\n";
    }
    else{
        cout<<"Game over after "<<tim<<" seconds\n";
    }
    cout<<livetot<<'\n';
    for(auto x:ant){
        cout<<x.age<<' '<<x.level<<' '<<x.hp<<' '<<x.x<<' '<<x.y<<'\n';
    }
}
int main(){
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    init();
    play();
    print();
    return 0;
}

压行版本。

#include<bits/stdc++.h>
using namespace std;
const int N=22;const double eps=1e-8;int n,m,num,radius,damage,endtime,tot,livetot,tim,dx[4]={0,1,0,-1},dy[4]={1,0,-1,0};bool running=false,cakefly=false;
struct Map{int information=0;bool use=false;}mp[N][N];
struct Ant{int age=0,level=0,hp=0,maxhp=0;pair<int,int>pos,last;bool havecake=false;};
list<Ant>ant;
struct Turret{bool havetarget=false,caketarget=false;pair<int,int>pos;double radius;list<Ant>::iterator target;}turret[N];
struct Vector{
    double x,y;
    const double pi=acos(-1);
    inline Vector(double a=0,double b=0){x=a,y=b;}
    inline friend Vector operator+(const Vector&a,const Vector&b){return Vector(a.x+b.x,a.y+b.y);}
    inline friend Vector operator-(const Vector&a,const Vector&b){return Vector(a.x-b.x,a.y-b.y);}
    inline friend Vector operator*(const Vector&a,const double&b){return Vector(a.x*b,a.y*b);}
    inline friend Vector operator/(const Vector&a,const double&b){return Vector(a.x/b,a.y/b);}
    inline friend double operator&(const Vector&a,const Vector&b){return a.x*b.y-a.y*b.x;}//叉积 
    inline friend double operator|(const Vector&a,const Vector&b){return a.x*b.x+a.y*b.y;}//点积
    inline double operator~()const{return sqrt(x*x+y*y);}//模长
    inline double operator!()const{return atan2(y,x);}//弧度*180/pi=度数
    inline double slope()const{return y/x;}
    inline int doublepos(double x)const{return (fabs(x)<eps)?0:((x<0)?-1:1);}
    inline Vector rotate(const double&a){return Vector(x*cos(a)-y*sin(a),x*sin(a)+y*cos(a));}
    inline double pointdistosegment(const Vector&p,const Vector&a,const Vector&b){
        Vector v=b-a,v0=p-a,v1=p-b;
        if(doublepos(v|v0)<0)return ~v0;
        if(doublepos(v|v1)>0)return ~v1;
        return fabs((v&v0)/~v);
    }
};
inline void antborn(){(livetot>5||mp[0][0].use==true)?0:(++tot,++livetot,ant.push_back({0,(tot-1)/6+1,(int)(4*pow(1.1,(tot-1)/6+1)),(int)(4*pow(1.1,(tot-1)/6+1)),{0,0},{0,0},false}),mp[0][0].use=true);}
inline void release(){for(auto x:ant)(x.havecake==true)?(mp[x.pos.first][x.pos.second].information+=5):(mp[x.pos.first][x.pos.second].information+=2);}
inline bool check(int x,int y){return mp[x][y].use==false&&x>=0&&y>=0&&x<=n&&y<=m;}
inline void antmove(){
    for(auto&x:ant){
        int pos,maxinformation=0,cnt=0;
        for(int i=0,tx,ty;i<4;i++)(check(tx=x.pos.first+dx[i],ty=x.pos.second+dy[i])==true&&x.last!=pair<int,int>{tx,ty}&&mp[tx][ty].information>=maxinformation)&&(pos=i,mp[tx][ty].information>maxinformation?cnt=1,maxinformation=mp[tx][ty].information:cnt++);
        if(cnt==0){x.last=x.pos;continue;}
        if(cnt>1)for(int i=0,tx,ty;i<4;i++)if(check(tx=x.pos.first+dx[i],ty=x.pos.second+dy[i])&&x.last!=pair<int,int>{tx,ty}&&mp[tx][ty].information==maxinformation){pos=i;break;}
        if((x.age+1)%5==0)for(int i=0,tx,ty;i<4;i++)if(((pos=(--pos<0)?3:pos)+1)&&(check(tx=x.pos.first+dx[pos],ty=x.pos.second+dy[pos])&&x.last!=pair<int,int>{tx,ty}))break;
        mp[x.last.first=x.pos.first][x.last.second=x.pos.second].use=false,mp[x.pos.first+=dx[pos]][x.pos.second+=dy[pos]].use=true;
    }
}
inline void checkcake(){if(cakefly==false)for(auto&x:ant)if(x.pos==pair<int,int>{n,m}){cakefly=x.havecake=true,x.hp=min(x.hp+(int)(1.0*x.maxhp/2.0),x.maxhp);break;}}
inline double distance(pair<int,int>a,pair<int,int>b){return sqrt((a.first-b.first)*(a.first-b.first)+(a.second-b.second)*(a.second-b.second));}
inline void attack(){
    for(int i=1;i<=num;i++){
        turret[i].havetarget=turret[i].caketarget=false,turret[i].radius=1e7;
        for(auto it=ant.begin();it!=ant.end();it++){
            double dis=distance(turret[i].pos,it->pos);
            if(dis<=radius+eps){
                turret[i].havetarget=true;
                if(it->havecake==true)turret[i].caketarget=true,turret[i].target=it;
                else if(dis<turret[i].radius&&turret[i].caketarget==false)turret[i].target=it,turret[i].radius=dis;
            }
            if(turret[i].caketarget==true)break;
        }
    }
    for(int i=1;i<=num;i++){
        if(turret[i].havetarget==false)continue;
        if(turret[i].caketarget==false){turret[i].target->hp-=damage;continue;}
        Vector a(turret[i].target->pos.first,turret[i].target->pos.second),b(turret[i].pos.first,turret[i].pos.second);
        for(auto&x:ant){
            if(x.havecake==true){x.hp-=damage;continue;}
            Vector p(x.pos.first,x.pos.second);
            if(p.pointdistosegment(p,a,b)<eps+0.5)x.hp-=damage;
        }
    }
}
inline void clear(){for(auto it=ant.begin();it!=ant.end();it++)(it->hp<0)&&(cakefly=(it->havecake==true)?false:cakefly,mp[it->pos.first][it->pos.second].use=false,it=ant.erase(it),it--,livetot--);}
inline bool gameover(){for(auto x:ant)if(x.havecake==true&&x.hp>=0&&x.pos==pair<int,int>{0,0})return true;return false;}
inline void update(){for(int i=0;i<=n;i++)for(int j=0;j<=m;j++)(mp[i][j].information)&&(mp[i][j].information--);for(auto&x:ant)x.age++;}
inline void init(){cin>>n>>m>>num>>damage>>radius;for(int i=1,x,y;i<=num;i++)cin>>x>>y,turret[i].pos={x,y},mp[x][y].use=true;cin>>endtime;}
inline void play(){for(tim=1;tim<=endtime;tim++){antborn(),release(),antmove(),checkcake(),attack(),clear();if(gameover())break;update();}}
inline void print(){(tim==endtime+1)?(cout<<"The game is going on\n",1):(cout<<"Game over after "<<tim<<" seconds\n",1);cout<<livetot<<'\n';for(auto x:ant)cout<<x.age<<' '<<x.level<<' '<<x.hp<<' '<<x.pos.first<<' '<<x.pos.second<<'\n';}
int main(){
    init();
    play();
    print();
    return 0;
}
posted @ 2022-11-14 18:00  半步蒟蒻  阅读(186)  评论(0)    收藏  举报