1 条题解

  • 0
    @ 2025-8-24 22:27:47

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar Karry5307
    兄弟会背叛你,女人会离开你,金钱会诱惑你,生活会刁难你,只有数学不会,不会就是不会,怎么学都不会

    搬运于2025-08-24 22:27:47,当前版本为作者最后更新于2021-01-01 22:37:21,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    题意

    略。

    题解

    我我我再也不做调参人了!

    参数是重新调的(因为原来的答案丢了),抢了个你谷首 A 还是蛮开心。/cy

    一开始想的是枚举白色团子匹配哪两个,如果能匹配就匹配,发现这东西只能写随机贪心,于是考虑变换一下枚举绿色或者粉色,大概这样:

    对于一个当前没有匹配的非白色团子,枚举八个方向看能不能匹配,如果能匹配且不会带来冲突则匹配,否则撤销与之冲突团子的匹配,然后类似匈牙利解决冲突问题。

    但是这个东西并不能一遍求出最优解,所以大概可以考虑刷一下。对于每一个情况随很多方案出来取个 max\max 得到最优方案。

    但是这个所谓的最优方案有些时候还不够,于是考虑用这个初始解去刷更好的解,类似模拟退火一样一开始随机的幅度很大,然后后面随机幅度很小来调整,然后多花点时间刷解应该能行。

    提交的答案是这样的:

    Data 1: 47220
    Data 2: 41984
    Data 3: 51391
    Data 4: 19129
    Data 5: 48625
    Data 6: 46503
    

    由于增加了许多一轮刷解时候的次数所以目前得到的结果比之前的那一份解法要好,如果大家有更好的答案可以联系我。

    下面的代码大概是这么用的:输入测试数据编号和参数(参数为 00 则为刷一个比较好的初始解存到 .out1 中,参数为 11 则意味着从 .out1 中得到一份好的初始解刷一个更好的),然后一轮大概是 500s 左右的样子可以跑出一个比较好的解,毕竟提答题就是看耐心以及算法的优秀程度。

    如果并行的话应该能够在 30min 之内跑完所有 6 个数据。

    代码

    #include<bits/stdc++.h>
    #pragma GCC optimize("Ofast,unroll-loops")
    using namespace std;
    typedef int ll;
    typedef long long int li;
    typedef pair<ll,ll> pii;
    const ll MAXN=505;
    vector<pii>v;
    ll n,m,r,rr,par,tp;
    string test;
    mt19937 mt(time(0));
    ll vx[8]={1,-1,0,0,1,-1,1,-1},vy[8]={0,0,1,-1,1,-1,-1,1};
    ll vis[MAXN][MAXN],match[MAXN][MAXN][2],matchr[MAXN][MAXN][2];
    char ch[MAXN][MAXN],chr[MAXN][MAXN],res[MAXN][MAXN];
    inline ll read()
    {
        register ll num=0,neg=1;
        register char ch=getchar();
        while(!isdigit(ch)&&ch!='-')
        {
            ch=getchar();
        }
        if(ch=='-')
        {
            neg=-1;
            ch=getchar();
        }
        while(isdigit(ch))
        {
            num=(num<<3)+(num<<1)+(ch-'0');
            ch=getchar();
        }
        return num*neg;
    }
    inline char getId(char x)
    {
        return x=='|'?0:x=='-'?1:x=='\\'?2:3;
    }
    inline char getOp(ll x)
    {
        return "|-\\/"[x>>1];
    }
    inline ll dfs(ll x,ll y)
    {
        ll wx,wy,px,py,cx,cy;
        if(vis[x][y])
        {
            return 0;
        }
        vis[x][y]=1,v.push_back((pii){x,y});
        for(register int i=0;i<8;i++)
        {
            wx=x+vx[i],wy=y+vy[i],px=wx+vx[i],py=wy+vy[i];
            if(ch[wx][wy]=='W'&&ch[px][py]+ch[x][y]=='P'+'G')
            {
                cx=match[px][py][0],cy=match[px][py][1],ch[wx][wy]=getOp(i);
                if(cx==-1||dfs(cx,cy))
                {
                    if(cx!=-1)
                    {
                        for(register int j=0;j<8;j++)
                        {
                            if(cx+2*vx[j]==px&&cy+2*vy[j]==py)
                            {
                                ch[cx+vx[j]][cy+vy[j]]='W';
                            }
                        }
                    }
                    match[px][py][0]=x,match[px][py][1]=y;  
                    match[x][y][0]=px,match[x][y][1]=py;
                    return 1;
                }   
                ch[wx][wy]='W';
            }
        }
        return 0;
    }
    inline void calc(ll op)
    {
        vector<pii>cc;
        for(register int i=1;i<=n;i++)
        {
            for(register int j=1;j<=m;j++)
            {
                ch[i][j]!='W'&&match[i][j][0]==-1?cc.push_back((pii){i,j}):(void)1;
            }
        }
        if(op)
        {
            shuffle(cc.begin(),cc.end(),mt);
        }
        for(auto i:cc)
        {
            if(match[i.first][i.second][0]==-1)
            {
                r+=dfs(i.first,i.second);
                for(auto j:v)
                {
                    vis[j.first][j.second]=0;
                }
                v.clear();
            }
        }
    }
    inline void calc1(ll c)
    {
        vector<pii>undo;
        memcpy(matchr,match,sizeof(match)),memcpy(chr,ch,sizeof(ch)),rr=r;
        for(register int i=1;i<=n;i++)
        {
            for(register int j=1;j<=m;j++)
            {
                !isupper(ch[i][j])?undo.push_back((pii){i,j}):(void)1;
            }
        }
        shuffle(undo.begin(),undo.end(),mt);
        for(auto i:undo)
        {
            if(!(mt()%(ll)ceil(1.5*c)))
            {
                ll x=i.first,y=i.second,tp=getId(ch[x][y]);
                ch[x][y]='W',r--;
                match[x+vx[tp<<1]][y+vy[tp<<1]][0]=-1;
                match[x+vx[tp<<1]][y+vy[tp<<1]][1]=-1;
                match[x+vx[tp<<1|1]][y+vy[tp<<1|1]][0]=-1;
                match[x+vx[tp<<1|1]][y+vy[tp<<1|1]][1]=-1;
            }
        }
        calc(1);
        if(r<rr)
        {
            memcpy(match,matchr,sizeof(match)),memcpy(ch,chr,sizeof(ch)),r=rr;
        }
    }
    int main()
    {
        cin>>test,par=read();
        if(par==0)
        {
            freopen((test+".in").c_str(),"r",stdin);
            freopen((test+".out1").c_str(),"w",stdout);
        }
        if(par==1)
        {
            freopen((test+".out1").c_str(),"r",stdin);
            freopen((test+".out").c_str(),"w",stdout);
        }
        srand(time(0));
        memset(match,-1,sizeof(match));
        if(par==1)
        {
            n=m=500;
        }
        else
        {
            n=read(),m=read();
        }
        fprintf(stderr,"%d %d\n",n,m);
        for(register int i=1;i<=n;i++)
        {
            scanf("%s",ch[i]+1);
        }
        fprintf(stderr,"%d\n",strlen(ch[1]+1));
        if(par)
        {
            for(register int i=1;i<=n;i++)
            {
                for(register int j=1;j<=m;j++)
                {
                    if(!isupper(ch[i][j]))
                    {
                        tp=getId(ch[i][j]),r++;
                        match[i+vx[tp<<1]][j+vy[tp<<1]][0]=i+vx[tp<<1|1];
                        match[i+vx[tp<<1]][j+vy[tp<<1]][1]=j+vy[tp<<1|1];
                        match[i+vx[tp<<1|1]][j+vy[tp<<1|1]][0]=i+vx[tp<<1];
                        match[i+vx[tp<<1|1]][j+vy[tp<<1|1]][1]=j+vy[tp<<1];
                    }
                }
            }
        }
        else
        {
            calc(0);
        }
        fprintf(stderr,"%d\n",r);
        for(register int i=1;i<=200;i++)
        {
            for(register int j=1;j<=60;j++)
            {
                calc1(i);
                if(j%10==0)
                {
                    fprintf(stderr,"%d\n",r);
                }
            }
        }
        fprintf(stderr,"%d\n",r);
        for(register int i=1;i<=n;i++)
        {
            printf("%s\n",ch[i]+1);
        }
    }
    
    • 1

    信息

    ID
    5852
    时间
    1000ms
    内存
    128MiB
    难度
    6
    标签
    递交数
    0
    已通过
    0
    上传者