题解:P13146 [GCJ 2018 #2] Graceful Chainsaw Jugglers
题目:
贪心:初始只能选 \((0,0)\),每次选 \((a,b)\) 会拓展出一个 \((a+1,b),(a,b+1)\)。
画一下这个图,是个长得很像树的 DAG(有向无环图)。
考虑递归,可以走上面和下面,但是上下有重。
这时我们令下面只能紧贴着下面走,然后我们发现这样就可以拆成两个子问题。
而走上面的路径又与其父节点面临同样的决策,所以我们把这种情况归为一类。
但是子节点的所有 \((a,b)\) 相当于父节点的 \((a+1,b)\),我们想要提前计算这个 \(1\) 就要枚举在这个点后选的点数。
dfs(qiu,r,b)
:从 \((0,0)\) 开始有 \(r\) 个红,\(b\) 个蓝,能不能选 \(qiu\) 个。
dfs2(qiu)
:从 \((0,0)\) 开始紧贴着下面走 \(qiu\) 步需要的蓝的个数。
#include<bits/stdc++.h>
using namespace std;
const int QAQ=1010;
int t,r,b,ans;
bitset<QAQ> f[QAQ][QAQ],vis[QAQ][QAQ];
/*
记忆化数组,用 bitset,不然开不下。
*/
#define mk make_pair
int dfs2(int qiu) {return (1+qiu)*qiu/2;}
bool dfs(int qiu,int r,int b)
{
if(r<0||b<0) return 0;
if(qiu-1<=0) return 1;
if(vis[qiu][r][b]) return f[qiu][r][b];
vis[qiu][r][b]=1;
for(int o1=0;o1<qiu;o1++)
if(dfs2(qiu-1-o1)<=b&&dfs(o1,r-o1,b-dfs2(qiu-1-o1)))
return f[qiu][r][b]=1,1;
return 0;
}
signed main()
{
cin>>t;
for(int i=1;i<=t;i++)
{
cin>>r>>b;
for(int j=r+b;j>=0;j--)
if(dfs(j+1,r,b))
{
cout<<"Case #"<<i<<": "<<j<<"\n";
break;
}
}
return 0;
}