AtCoder Beginner Contest 453

D - Go Straight

思路:条件判断的BFS,注意不要存储完整路径字符串 ,改为 记录前驱状态,到达终点后反向回溯构建路径。

开三个数组记录前驱:

cpp 复制代码
int pre_x[N][N][4];   // 前驱的 x 坐标
int pre_y[N][N][4];   // 前驱的 y 坐标
int pre_dir[N][N][4]; // 前驱的方向(0~3),起点设为 -1
int move_dir[N][N][4];// 从父状态到当前状态所用的方向

Code:

cpp 复制代码
using aii=array<int,3>;
const int N = 5e6,mod=998244353;
typedef pair<int,int> PII;
#define fi first
#define se second
typedef pair<aii,string> pai;
int n,m;

bool st[1005][1005][4];
int ne[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
char a[1005][1005];
int sx,sy,ex,ey;
string s[4]={"R","L","D","U"};
int dist[1005][1005][4];
int prex[1005][1005][4],prey[1005][1005][4],predir[1005][1005][4],movedir[1005][1005][4];
bool ok(int tx,int ty)
{
   if(tx>=0&&tx<n&&ty>=0&&ty<m)
      {
       return true;
      }
      return false;
}

void print(int x,int y,int i)
{
    if(predir[x][y][i]==-1)
    {
        cout<<s[i];
        return ;
    }
    print(prex[x][y][i],prey[x][y][i],predir[x][y][i]);
    cout<<s[i];
}
void Dijkstra()
{
   queue<aii> heap;
   for(int i=0;i<4;i++)
    {
      int tx=sx+ne[i][0],ty=sy+ne[i][1];
       st[sx][sy][i]=1;
      if(tx>=0&&tx<n&&ty>=0&&ty<m)
      {
          
        if(a[tx][ty]!='#')
        {
            st[tx][ty][i]=1;
            heap.push({tx,ty,i});
            dist[tx][ty][i]=1;
            prex[tx][ty][i]=sx;
            prey[tx][ty][i]=sy;
            predir[tx][ty][i]=-1;
            movedir[tx][ty][i]=i;
        }
          
      }
    }

    while(heap.size())
    {
      auto [x,y,c]=heap.front();heap.pop();
        //auto [x,y,c]=arr;
     
      if(a[x][y]=='G')
      {
        cout<<"Yes"<<endl;
        print(x,y,c);
        return ;
      }

  //    if(st[x][y][c]) continue;
      
      if(a[x][y]=='.')
      {
        for(int i=0;i<4;i++)
        {
          int tx=x+ne[i][0],ty=y+ne[i][1];
          if(ok(tx,ty)&&a[tx][ty]!='#'&&!st[tx][ty][i]&&dist[x][y][c]+1<=N)
          {
          
              st[tx][ty][i]=1;
               prex[tx][ty][i]=x;
            prey[tx][ty][i]=y;
            predir[tx][ty][i]=c;
            movedir[tx][ty][i]=i;
            heap.push({tx,ty,i});
          }
        }
      }
      else if(a[x][y]=='o')
      {
        int tx=x+ne[c][0],ty=y+ne[c][1];
        if(ok(tx,ty)&&a[tx][ty]!='#'&&!st[tx][ty][c]&&dist[x][y][c]+1<=N)
        {
  
            st[tx][ty][c]=1;
             prex[tx][ty][c]=x;
            prey[tx][ty][c]=y;
            predir[tx][ty][c]=c;
            movedir[tx][ty][c]=c;
          heap.push({tx,ty,c});
        }
      }
      else if(a[x][y]=='x')
      {
        for(int i=0;i<4;i++)
        {
          if(i==c) continue;
          int tx=x+ne[i][0],ty=y+ne[i][1];
          if(ok(tx,ty)&&a[tx][ty]!='#'&&!st[tx][ty][i]&&dist[x][y][c]+1<=N)
          {

              st[tx][ty][i]=1;
               prex[tx][ty][i]=x;
            prey[tx][ty][i]=y;
            predir[tx][ty][i]=c;
            movedir[tx][ty][i]=i;
            heap.push({tx,ty,i});
          }
        }
      }

    }
    cout<<"No";
}
void solve()
{
   cin>>n>>m;
   for(int i=0;i<n;i++)
    for(int j=0;j<m;j++)
    {
      cin>>a[i][j];
      if(a[i][j]=='S') sx=i,sy=j;
      else if(a[i][j]=='G') ex=i,ey=j;
    }
    Dijkstra();
}

E - Team Division

思路:差分求前缀和

1.只能选A Li Ri

2.只能选B n-Ri n-Li

3.A和B都可以 max(Li,n-Ri) min(Ri,n-Li)

对三个数组进行差分求前缀和

枚举A队人数

x=cntAi-cntCi表示A队最多为i人的情况下有x人只能选A队

y=cntBi-cntCi表示A队最多为i人的情况下有y人只能选B队

z=cntCi表示有z人可以去任意一队

如果三者加起来等于n方案数为C(z,i-x)

Code:

cpp 复制代码
int fact[N],infact[N];

int qmi(int a,int b)
{
  int res=1;
  while(b)
  {
    if(b&1) res=res*a%mod;
    b>>=1;
    a=a*a%mod;
  }
  return res;
}
int C(int x,int y)
{
  if(x<0||y<0||x<y) return 0;
  return fact[x]*infact[y]%mod*infact[x-y]%mod;
}
void solve()
{
  fact[0]=infact[0]=1;
  for(int i=1;i<N;i++)
  {
    fact[i]=fact[i-1]*i%mod;
    infact[i]=infact[i-1]*qmi(i,mod-2)%mod;
  }
  int n;cin>>n;
   vector<int> cnt1(n+5,0),cnt2(n+5,0),cnt3(n+5,0);
   for(int i=0;i<n;i++)
   {
    int l,r;cin>>l>>r;
    cnt1[l]++,cnt1[r+1]--;
    cnt2[n-r]++,cnt2[n-l+1]--;
    int l1=max(l,n-r),r1=min(r,n-l);
    if(l1<=r1) cnt3[l1]++,cnt3[r1+1]--;
   }
   for(int i=1;i<=n;i++)
   {
    cnt1[i]+=cnt1[i-1];
    cnt2[i]+=cnt2[i-1];
    cnt3[i]+=cnt3[i-1];
   }
   int ans=0;
   for(int i=1;i<=n;i++)
   {
    int x=cnt1[i]-cnt3[i],y=cnt2[i]-cnt3[i];
    if(x+y+cnt3[i]==n) ans=(ans+C(cnt3[i],i-x))%mod;
   }
   cout<<ans;
}
相关推荐
To_OC3 小时前
LC 1 两数之和:面试第一道必考题,暴力解法直接被面试官 pass
javascript·算法·leetcode
鱼鱼不愚与7 小时前
《原来如此 | 第01期:为什么导航软件能预测红绿灯倒计时?》
算法
博客180011 小时前
酷宝的使用方法,超好用的免费界面库,C++、MFC可用
c++·mfc·界面库·库来帮·酷宝
郝学胜_神的一滴12 小时前
CMake 026:属性体系精讲、四大作用域全解 & 实战代码落地
c++·cmake
复杂网络12 小时前
论最小 Agent 计算机的形态
算法
kisshyshy1 天前
🍦 雪糕、食堂、火车厢:三幅漫画吃透栈、队列与链表
javascript·算法
众少成多积小致巨1 天前
JNI (Java Native Interface) 技术手册中文参考指南
android·java·c++
猿人谷1 天前
不只是 CPU 阈值:STAR 如何用 GAT + Transformer 做容器级自动扩缩容?
人工智能·算法
复杂网络1 天前
Stable Diffusion 视觉大模型微调技术深度调研
算法