題意:n∗m
n*mn∗
m(n,m<=11)的矩陣,填1∗2
1*21∗
2或2∗
12*1
2∗1方塊,求方案數
解析:
以前寫過狀壓的做法,直接一行一行維護,現在寫輪廓線的做法
注意:當前填紅點的意思是,以紅點作為方塊的右下角
因為方塊長度為2,所以對紅點位置有三種操作
向上填:為了使所有方塊填滿,如果a方塊沒有被填,則必須向上填(紅+a)
向左填:當上面已經填好時,而左邊沒有填時,可以向左填(紅+b)
不填:當上面填好後,可以選擇不填
細節:
#include
#include
#include
#include
using namespace std;
#define ll long long
ll dp[2]
[2090];
intmain()
}}}}
int id=n*m;id&=1
;printf
("%lld\n"
,dp[id]
[maxstate]);
}}
\\\;
\\\;
題意:矩陣(n*n,n<=20)取一些數,使這些數的和最大,且任何兩個數都不能相鄰
解析:
和上題一模一樣的思路,變成當上面和左邊都空時才能插入,再把陣列改大一點就過了。
當然,這裡因為答案只會越來越大,所以就省略了memset的操作。但是為了當前的更新不干擾前面的狀態,還是需要用滾動陣列。
#include
#include
#include
#include
using namespace std;
#define ll long long
ll dp[2]
[1100000];
ll v[21]
[21];
intmain()
}memset
(dp,0,
sizeof
(dp));
int maxstate=(1
<
;for
(int i=
1;i<=n;i++)}
}int id=n*m;id&=1
; ll ans=0;
for(
int i=
0;i<=maxstate;i++
)ans=
max(ans,dp[id]
[i])
;printf
("%lld\n"
,ans);}
}
\\\;
\\\;
題意:在上題的基礎上,新增了對稱相鄰((1,1)和(2,2))也不能同時選的條件。而且蛋疼的是沒有告訴n,需要自己從字串得出來。
解析:
也就是對於紅點多了cd兩個點的判斷,但是比較麻煩的是,到了紅點之後,狀態k中記錄的位置是b點的狀態,所以需要再開拓一位記錄c點的狀態。而d點的狀態是直接有記錄的。
有個題外話,雖然這兩題沒有用,前面拼矩陣需要所有都填滿,所以初始狀態為(11…11),但是這裡前面對接下來的影響是不能相鄰,所以如果有初始狀態,應該是(00…00)。
#include
#include
#include
#include
using namespace std;
#define ll long long
ll dp[2]
[132000][
2];//最後一維代表當前位置的上方位置的狀態
ll v[16]
[16];
char x[
100]
;int
data_in()
}else
i++;}
if(num)
for(i=
2;i<=n;i++)}
return n;
}void
deal
(int n)
else
if(j==n)
else}}
}}ll ans=0;
for(
int i=
0;i<=maxstate;i++)}
printf
("%d\n"
,ans);}
intmain()
return0;
}
插頭DP 輪廓線DP
題解 p5056 模板 插頭dp gnaq uparrow 學習資料,大部分賀的,有一些些的改動與自己的補充 插頭 dp 是一類用狀壓 dp 來處理連通性問題的 dp 方法。常見的型別 棋盤插頭 dp 連通性問題 迴路問題,路徑問題,生成樹問題等 插頭 dp 本質上式狀壓 dp!一般設 dp i,s...
group 狀壓dp,輪廓線
神仙題。但是難得的傻孩子cbx沒有喊題解,所以也就難得的自己想出來了乙個如此神仙的題。如果是自己想的,說它神仙是不是有點不合適啊。反正的確不好像。關鍵就在於這個標籤。頹完標籤就差不多會了。cbx那麼快就想出來了。2個小時?廢話多了。先考慮暴力。對於16的資料範圍當然要考慮狀壓,狀態表示每乙個位置是否...
大樓輪廓線
輸入第一行乙個數表示有n座大樓,後面依次輸入n行,每一行表示大樓的起始點,終點和高度,輸出為大樓輪廓資訊 如下圖 第一行輸出為3 後面有三行輸入表示大樓的資訊 第二行為 1 3 3 第三行為 2 4 4 第三行為 5 6 1 輸出大樓輪廓資訊 第一行 1 2 3 第二行 2 4 4 第三行 5 6 ...