題解:P13146 [GCJ 2018 #2] Graceful Chainsaw Jugglers
題目:
貪心:初始只能選 \((0,0)\),每次選 \((a,b)\) 會(huì)拓展出一個(gè) \((a+1,b),(a,b+1)\)。
畫一下這個(gè)圖,是個(gè)長(zhǎng)得很像樹的 DAG(有向無(wú)環(huán)圖)。
考慮遞歸,可以走上面和下面,但是上下有重。
這時(shí)我們令下面只能緊貼著下面走,然后我們發(fā)現(xiàn)這樣就可以拆成兩個(gè)子問(wèn)題。
而走上面的路徑又與其父節(jié)點(diǎn)面臨同樣的決策,所以我們把這種情況歸為一類。
但是子節(jié)點(diǎn)的所有 \((a,b)\) 相當(dāng)于父節(jié)點(diǎn)的 \((a+1,b)\),我們想要提前計(jì)算這個(gè) \(1\) 就要枚舉在這個(gè)點(diǎn)后選的點(diǎn)數(shù)。
dfs(qiu,r,b):從 \((0,0)\) 開始有 \(r\) 個(gè)紅,\(b\) 個(gè)藍(lán),能不能選 \(qiu\) 個(gè)。
dfs2(qiu):從 \((0,0)\) 開始緊貼著下面走 \(qiu\) 步需要的藍(lán)的個(gè)數(shù)。
#include<bits/stdc++.h>
using namespace std;
const int QAQ=1010;
int t,r,b,ans;
bitset<QAQ> f[QAQ][QAQ],vis[QAQ][QAQ];
/*
記憶化數(shù)組,用 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;
}

浙公網(wǎng)安備 33010602011771號(hào)