



思路:条件判断的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();
}



思路:差分求前缀和
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;
}