题解: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;
}
posted @ 2025-09-29 15:32  _a1a2a3a4a5  阅读(16)  评论(0)    收藏  举报