炮兵陣地
這道題之前已經討論過二進位制狀壓的方法了,通過 滾動陣列+預處理 的方法可以達到極高效率。
但是這裡給出一種更具有普適性的方法。
對於和之前多個階段有關聯的 dp,我們可以使用多進製狀壓來處理。
具體方法:假設進行 \(k\) 進製狀壓,將每一位的狀態表示為 \(0\)~\(k-1\) 中的某個數,規定狀態之間的轉移方式求解。
例如本題就可以將每行的狀態縮為三進製數,用 \(f[i,j]\) 表示第 \(i\) 行的狀態為 \(j\) 時的最多炮兵方案,
如果某個格仔有炮兵我們就將其表示為 \(2\),然後強制 \(2\) 的下面為 \(1\),\(1\) 的下面為 \(0\)。
那麼顯然我們的判定為同行的 \(2\) 之間的距離 \(>2\)。
但是通常這種情況下的狀態之間比較難轉移,所以可以使用 dfs 進行轉移。
具體實現見下。
#include#include#include#define n 110
#define m 59049
using namespace std;
int n,m,now[15];
int f[n][m+10];
int p[12]=;
char s[n][15];
void change(int row,int k)
return;
}void dfs(int row,int pos,int last,int k,int cnt)
if(now[pos]==2)
if(now[pos]==1) dfs(row,pos+1,last,k+p[pos],cnt);
if(now[pos]==0 || now[pos]==2) dfs(row,pos+1,last,k,cnt);//填 2 的位也可以填 0。
}int main()
int ans=0;
for(int i=0;iprintf("%d\n",ans);
return 0;
}
P2704 NOI2001 炮兵陣地
題目鏈結 狀壓dp。這個炮可以打到上面兩行,這個點卡了我很久,我一開始就壓一行的狀態,發現會無線套娃 當前行可能會打到上兩行,你還不能只判斷當前行與上一行是否匹配,還得判斷上兩行 判了上一行還要判斷上一行的上兩行。為了解決這個問題,我們可以直接把兩行的狀態放到乙個陣列裡,這樣問題就解決了。轉移方程 ...
P2704 NOI2001 炮兵陣地 題解
題目描述就不贅述了。解題思路 這道題的判斷合法的方式比較常見,簡單位運算即可,關鍵是空間和狀態轉移方程。預處理 可以證明有效的方案數不會超過200,這個數字只是我估算的上界,不嚴格,預處理出每一行的方案即可。狀態轉移方程 每一行由上一行遞推得到,f i j k 表示前i行,第i行狀態為j,第i 1行...
洛谷 P2704 NOI2001 炮兵陣地
給出n m的地圖,有很多空地p跟山地h,炮台可以攻擊周邊 求最多能放多少個炮台並且他們互不攻擊。n 100 m 10 這題是狀壓dp的一道經典題目,對於每行10個東東可以放就是2 10種可能,這樣轉移就會tle 所以我們發現因為任意2個炮之間距離至少為2,所以我們每行存在的可行狀態至多不超過2 5 ...