首页 > 其他分享 >P6474 [NOI Online #2 入门组] 荆轲刺秦王 题解

P6474 [NOI Online #2 入门组] 荆轲刺秦王 题解

时间:2024-12-14 22:12:33浏览次数:10  
标签:node sy sx int 题解 差分 BFS Online P6474

荆轲将会臭名昭著

首先 $15$ 做法很简单,那就是直接 `cout<<-1`

考虑用 BFS 来解思路很简单,但是怎么求每个士兵的控制范围呢?

直接暴力时间复杂度是 $O(nma^2)$ 当然过不了一定会TLE。

所以,只需要差分+前缀和即可。

说起来简单,实现起来也简单。

然后,单打广搜大家应该都会了,可是出题人的恶魔 $18$ 点可以让你的代码慢到爆炸!

怎么剪枝呢?也很简单。

只需将当前步数大于之前已走到终点点数的点删去就可以了。

就这么简单,但我还是打了5个多小时。

然后...

正片开始!

起初,神创造了差分。标记数组是空虚混沌的,渊面黑暗,神的灵运行在差分的左右端点上。

for(int i=1;i<=n;i++)
{
    for(int j=1;j<=m;j++)
    {
        scanf("%s",s);
        if(s[0]=='S')
        {
            sx=i;
            sy=j;
        }
        else if(s[0]=='T')
        {
            tx=i;
            ty=j;
        }
        else if(s[0]!='.')
        {
            pers[i][j]=true;
            int len=strlen(s),num=0;
            for(int k=0;k<len;k++)
            {
                num=num*10+s[k]-'0';
            }
            for(int t=max(1,i-num+1);t<=min(n,i+num-1);t++)
            {
                int l=max(1,j-num+1+abs(i-t));
                int r=min(m,j+num-1-abs(i-t));
                cov[t][l]++;
                cov[t][r+1]--;
            }
        }
    }
}

神说差分数组要有值,与是差分数组变有了值。

for(int i=1;i<=n;i++)
{
    for(int j=1;j<=m;j++)
    {
        cov[i][j]+=cov[i][j-1];
    }
}

 

神看这值是对的,与是就把差分数组的预处理分为两段。有晚上,有早晨,是第一日。

for(int i=1;i<=n;i++)
{
    for(int j=1;j<=m;j++)
    {
        scanf("%s",s);
        if(s[0]=='S')
        {
            sx=i;
            sy=j;
        }
        else if(s[0]=='T')
        {
            tx=i;
            ty=j;
        }
        else if(s[0]!='.')
        {
            pers[i][j]=true;
            int len=strlen(s),num=0;
            for(int k=0;k<len;k++)
            {
                num=num*10+s[k]-'0';
            }
            for(int t=max(1,i-num+1);t<=min(n,i+num-1);t++)
            {
                int l=max(1,j-num+1+abs(i-t));
                int r=min(m,j+num-1-abs(i-t));
                cov[t][l]++;
                cov[t][r+1]--;
            }
        }
    }
}


for(int i=1;i<=n;i++)
{
    for(int j=1;j<=m;j++)
    {
        cov[i][j]+=cov[i][j-1];
    }
}

 

神说数组之间要有 BFS 将其应用,神就造出了 BFS,将 BFS 以外叫做#?,BFS 以内叫做?#,这样就成了,神称 BFS 为函数,有晚上,有早晨,是第二日。

void bfs()
{
     queue<node>q;
    q.push(#??#);
}

...

OK,95分大成!

满分做法啊...

[好好研究](https://www.luogu.com.cn/discuss/281304)[.](https://www.luogu.com.cn/paste/fpmecy7i)

 

当然,上面说了,自己改吧!

我把95分的贴出来,100的就不贴了。

const int N=360,M=20;
int n,m,c1,c2,dist;
int sx,sy,tx,ty;
int cov[N][N];
bool pers[N][N];
struct node
{
    int x,y,u1,u2;
    node(int v1,int v2,int v3,int v4) :
    x(v1),y(v2),u1(v3),u2(v4) {}
};
int d[N][N][M][M];
int vis[N][N][M][M];
const int dx[8]={-1,0,1,0,-1,1,1,-1},dy[8]={0,1,0,-1,1,1,-1,-1};
bool cmp(int x,int y)
{
    return 1<=x&&x<=n&&1<=y&&y<=m;
}
void bfs()
{
    queue<node>q;
    d[sx][sy][0][0]=0;
    vis[sx][sy][0][0]=true;
    q.push((node){sx,sy,0,0});
    while(!q.empty())
    {
        node u=q.front();
        q.pop();
        for(int i=0;i<8;i++)
        {
            int nx=u.x+dx[i];
            int ny=u.y+dy[i];
            if(cmp(nx,ny)&&!pers[nx][ny])
            {
                //cout<<nx<<" "<<ny<<" "<<u.x<<" "<<u.y<<" ";
                if(cov[nx][ny])
                {
                    if(u.u1+1<=c1&&!vis[nx][ny][u.u1+1][u.u2])
                    {
                        d[nx][ny][u.u1+1][u.u2]=d[u.x][u.y][u.u1][u.u2]+1;
                        vis[nx][ny][u.u1+1][u.u2]=true;
                        //cout<<nx<<" "<<ny<<"\n";
                        q.push((node){nx,ny,u.u1+1,u.u2});       
                    }
                }
                else
                {
                    if(!vis[nx][ny][u.u1][u.u2])
                    {
                        d[nx][ny][u.u1][u.u2]=d[u.x][u.y][u.u1][u.u2]+1;
                        vis[nx][ny][u.u1][u.u2]=true;
                        //cout<<nx<<" "<<ny<<"\n";
                        q.push((node){nx,ny,u.u1,u.u2});
                    }
                }
            }
        }
        if(u.u2+1<=c2)
        {
            for(int i=0;i<4;i++)
            {
                int nx=u.x+dx[i]*dist,ny=u.y+dy[i]*dist;
                if(cmp(nx,ny)&&!pers[nx][ny])
                {
                    if(cov[nx][ny])
                    {
                        if(u.u1+1<=c1&&!vis[nx][ny][u.u1+1][u.u2+1])
                        {
                            d[nx][ny][u.u1+1][u.u2+1]=d[u.x][u.y][u.u1][u.u2]+1;
                            vis[nx][ny][u.u1+1][u.u2+1]=true;
                            //cout<<nx<<" "<<ny<<"\n";
                            q.push((node){nx,ny,u.u1+1,u.u2+1});
                        }
                    }
                    else
                    {
                        if(!vis[nx][ny][u.u1][u.u2+1])
                        {
                            d[nx][ny][u.u1][u.u2+1]=d[u.x][u.y][u.u1][u.u2]+1;
                            vis[nx][ny][u.u1][u.u2+1]=true;
                            //cout<<nx<<" "<<ny<<"\n";
                            q.push((node){nx,ny,u.u1,u.u2+1});
                        }
                    }
                }
            }
        }
    }
    return ;
}
int main()
{
    cin>>n>>m>>c1>>c2>>dist;
    char s[4];
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            scanf("%s",s);
            if(s[0]=='S')
            {
                sx=i;
                sy=j;
            }
            else if(s[0]=='T')
            {
                tx=i;
                ty=j;
            }
            else if(s[0]!='.')
            {
                pers[i][j]=true;
                int len=strlen(s),num=0;
                for(int k=0;k<len;k++)
                {
                    num=num*10+s[k]-'0';
                }
                for(int t=max(1,i-num+1);t<=min(n,i+num-1);t++)
                {
                    int l=max(1,j-num+1+abs(i-t));
                    int r=min(m,j+num-1-abs(i-t));
                    //cout<<l<<" "<<r<<"\n";
                    cov[t][l]++;
                    cov[t][r+1]--;
                }
            }
        }
    }
    //cout<<"qidian "<<sx<<" "<<sy<<" zhongdian "<<tx<<" "<<ty<<"\n";
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            cov[i][j]+=cov[i][j-1];
        }
    }
    /*for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            cout<<cov[i][j]<<" ";
        }
        cout<<"\n";
    }*/
    bfs();
    int t=n*m,u1,u2;
    for(int i=0;i<=max(c1,c2);i++)
    {
        for(int j=0;j<=max(c1,c2);j++)
        {
            if(vis[tx][ty][j][i]&&d[tx][ty][j][i]<t)
            {
                t=d[tx][ty][j][i];
                u1=j;
                u2=i;
            }
        
        }
    }
    if(t==n*m)
    {
        cout<<-1;
    }
    else
    {
        cout<<t<<" "<<u1<<" "<<u2;
    }
    return 0;
}

 

标签:node,sy,sx,int,题解,差分,BFS,Online,P6474
From: https://www.cnblogs.com/-Acheron-/p/18607288

相关文章

  • AT_kupc2019_g ABCのG問題题解
    这题的难度不怎么好说,不过我认为还是挺简单的。我们可以把答案看成由多个子图构成的图,这样我们只需要手打一个小子图,从中推出完整的答案。-把小于子图范围的地方填上子图的字母-如果这个点的横坐标或纵坐标小于子图范围就填上$T_{i,0}$或$T_{0,j}$详见注释intmain(){......
  • [BZOJ3811] 玛里苟斯 题解
    不得不说这题的确挺苟的。注:下述“引理”表示:对于长度为\(n\)的数组\(V\),其线性基为\(B\),定义\(c_v=\bigoplus\limits_{a\inv}a\),\(num_k=\sum\limits_{v\subseteqV}[c_v=k]\),则\(\forallk\in\mathbb{N},num_k\in\{0,2^{n-|B|}\}\)。对于\(k=1\)的情况,容易想到按......
  • 机载电脑通过TypeC连接Pixhawk 6c (PX4)后的状态确认及问题解决
    在三个终端依次运行命令查看连接状态roscoeroslaunchmavrospx4.launchrostopicecho/mavros/state1.运行mavrospx4.lauch时udp1报错“networkisunreachable”原因:网关未设置解决方法:先通过使用route命令查看默认ip,发现网关未设置,再通过以下命令设置网关:sudorout......
  • 【决策单调性】P3648 [APIO2014] 序列分割 题解
    题目链接:P3648[APIO2014]序列分割(注:由于本题解的状态转移方程需要用到\(k\),所以原题中的\(k\)对应本题解中的\(m\)。)给你一个长度为\(n\)的序列\(A_1,A_2,...,A_n\),一开始把它看作一个块。初始你的分数为\(0\),现在你需要进行下列操作恰好\(m\)次:选一个块,并从一处......
  • ARC132E题解
    简要题意有\(n\)个方块,每个方块有一个初始状态可能为左右或者空。每次操作随机选择一个空进行操作。每次操作可以向左或者向右走一直到下一个空或者走出边界,走到的每个格子会变成左或者右,这取决于移动方向。求无法操作时方格为左的期望数。数据范围:\(n\le10^5\)。题解首先......
  • 2024年12月GESPC++三级真题解析
    一、单选题(每题2分,共30分)题目123456789101112131415答案BDAADBCAADDCDCA1.下列二进制表示的十进制数值分别是()[10000011]原=()[10000011]补=()A.-125,-3B.-3,-125C.-3,-3D.-125,-125【答案】B【考纲知识点】原码和补码的计算及转换【......
  • P10370 「LAOI-4」Mex Tower (Hard ver.) 题解
    有一定难度的思维题。题目传送门思路首先,\(\operatorname{mex}(x,y)\)的结果一定为\(0,1,2\),因为只有两个数,所以结果最多为\(2\)(\(x=1,y=0\)或\(x=0,y=1\)时)。因此,可以将问题转化为最后的数是否为\(2\)。考虑倒推,当\(n=1\)时,显然只能为\(2\);要从\(n=2\)的情况变为......
  • P10433 [JOISC 2024 Day2] 棋盘游戏 题解
    Description有一个供\(K\)个玩家玩的棋盘游戏。该游戏的棋盘由\(N\)个编号从1到\(N\)的单元格和\(M\)条编号从1到\(M\)的路径组成,其中路径\(j\)(\(1≤j≤M\))双向连接着单元格\(U_j\)和\(V_j\)。棋盘上有两种类型的单元格:重新激活单元格和停止单元格。这些......
  • P8998 [CEOI2022] Prize 题解
    Description这是一道交互题。Tomislav在睡梦中想到了一个问题:给定两棵大小为\(N\)的树,树上的节点按\(1\simN\)分别编号,树则分别编号为树\(1\),树\(2\),树有边权,但是边权被隐藏了起来。Tomislav需要向交互库提供一个大小为\(K\)的编号的子集\(S\),在选择了这个集合后,小......
  • uniapp的uview2.0框架u--textarea组件(或uv-ui uv-textarea)(或uviewui u--textarea)无法
    问题描述在使用uniapp的uview2.0框架u–textarea组件时,想要使u–textarea支持换行输入,但是默认不支持换行输入,各种百度,没有找到解决问题的方案,最后只有查看源码如下但发现源码没有对属性有过多的处理,我开始怀疑是不是原生组件又问题,但是测试之后发现原生组件并没有问题,经过一天......