ABC221G 题解
ABC221G 题解
upd:2025.9.10 你是不是其实是假的
原来上一次写博客已经是 thuwc 了么,为了防止下一篇就是省选游记 赶紧写篇博客证明我还活着
发现问题很像一个背包啊,但是一个点有四个状态,二维背包显然没有一个合理的复杂度通过此题
发现限制 \(x+y\) 与 \(x-y\) 和分别限制 \(x\),\(y\)是等价的,而这样可以让两边背包分别做,做完合并,大概等价于绕 \((0,0)\) 旋转 \(\frac{\pi}{4}\) 这样子
所以做两遍背包之后记录方案,最后合并就完了
考虑怎么做这个背包
我们考虑 Uplifting Excursion 的做法,先尽量多的选,然后调整即可
首先如果合法的话一定有一种方案能让我们所有转移都在 \([T-D,T+D]\) 之间完成所有转移
因为我们只关心可达性,没有权值,所以每个点第一次到达的状态就是最优状态
记录每个点的方案,bfs暴力尝试扩展即可,复杂度 \(O(nD)\)
代码非常好写!
点击查看代码
#include<bits/stdc++.h>
using namespace std;
using llt=long long;
const llt N=2010,D=3600;
llt n,A,B,d[N];bool vis[N<<2],ans=1;
bitset<N> s[N<<2],bs,x,y;queue<llt> qu;
void bfs(llt now)
{
qu.push(now);
while(!qu.empty())
{
now=qu.front();qu.pop();
for(int i=1;i<=n;i++)
if(s[now][i]) {if(now-2*d[i]>=0&&!vis[now-2*d[i]]) vis[now-2*d[i]]=1,s[now-2*d[i]]=s[now],s[now-2*d[i]].flip(i),qu.push(now-2*d[i]); }
else {if(now+2*d[i]<=2*D&&!vis[now+2*d[i]]) vis[now+2*d[i]]=1,s[now+2*d[i]]=s[now],s[now+2*d[i]].flip(i),qu.push(now+2*d[i]); }
}
}
bool solve(llt v)
{
llt sum=0;bs=0;memset(vis,0,sizeof(vis));for(int i=0;i<=2*D;i++) s[i]=0;
for(int i=1;i<=n;i++) sum-=d[i];
if(sum>v) return 0;
for(int i=1;i<=n;i++){bs[i]=1;sum+=2*d[i];if(sum>=v) break;}
if(sum<v) return 0;
s[sum-v+D]=bs;bfs(sum-v+D);
return vis[D];
}
int main()
{
#ifdef LOCAL
freopen("2.in","r",stdin);
freopen("2.out","w",stdout);
#endif
scanf("%lld%lld%lld",&n,&A,&B);
for(int i=1;i<=n;i++) scanf("%lld",&d[i]);
ans&=solve(A+B);x=s[D];ans&=solve(A-B);y=s[D];
if(ans)
{
puts("Yes");
for(int i=1;i<=n;i++)
if(x[i]&&y[i]) printf("R");
else if(x[i]) printf("U");
else if(y[i]) printf("D");
else printf("L");
}
else puts("No");
return 0;
}
浙公网安备 33010602011771号