BZOJ2331 SCOI2011 地板 題解

2022-05-16 16:03:45 字數 2199 閱讀 2125

題面複製於洛谷

鋪設完成後,客廳裡面所有沒有柱子的地方都必須鋪上地板,但同乙個地方不能被鋪多次。

輸入格式:

輸入的第一行包含兩個整數,r和c,表示客廳的大小。接著是r行,每行c個字元。'_'表示對應的位置是空的,必須鋪地板;'*'表示對應的位置有柱子,不能鋪地板。

輸出格式:

輸出一行,包含乙個整數,表示鋪滿整個客廳的方案數。由於這個數可能很大,只需輸出它除以20110520的餘數。

輸入樣例#1: 

2 2

*___

輸出樣例#1: 

1
輸入樣例#2: 

3 3

____*_

___

輸出樣例#2: 

8

參考了:

我終於可以告別插頭dp啦233333……

這道題的難點在於將插頭dp的插頭的定義進行修改。

0:無插頭

1:有插頭且當前格仔所在的地板能再轉彎。

2:有插頭且當前格仔所在的地板不能再轉彎。

有了這些就可以按照插頭dp的思想進行分情況討論了:

(摘自參考部落格)

1.00-->22 或 10 或 01

2.11-->00

3.10-->20 或 01

20-->00 或 02

4.01-->10 或 02

02-->00 或 20

最終把所有情況列舉累加即可。

ps:第二種情況的11轉換成了00實質上是11相交的地方變成了這塊地板的轉折點(也可以理解為兩塊地板並在了一起)。

#include#include

#include

using

namespace

std;

typedef

long

long

ll;const

int inf=2147483647

;const

int mod=300000

;const

int m=1000005

;const

int p=20110520

;struct

nodeedge[m];

inthead[m],cnt;

intn,m;

bool mp[105][105

];int

cur,pre;

int state[2

][m];

ll ans[

2][m],cntt;

int tot[2

];int bit[15

];inline

void

getbit()

inline

void add(int u,int

v)void insert(int

now,ll num)

}add(u,++tot[cur]);

state[cur][tot[cur]]=now;

ans[cur][tot[cur]]=num%p;

return;}

void

plugdp()

for(int j=1;j<=m;j++)

else

if(!is_down&&!is_right)

else

if(is_down&&!is_right)

else

}else

if(!is_down&&is_right)

else

}else

if(is_down==1&&is_right==1

) insert(now-(1

<1])-(1

}for(int k=1;k<=tot[cur];k++)cntt+=ans[cur][k];

return;}

intmain()}}

else}}

plugdp();

printf(

"%lld\n

",cntt);

return0;

}

P2331 SCOI2005 最大子矩陣

這裡有乙個n m的矩陣,請你選出其中k個子矩陣,使得這個k個子矩陣分值之和最大。注意 選出的k個子矩陣不能相互重疊。其中 1 le n le 100,1 le m le 2,1 le k le 10.m 只有 1 和 2 兩種取值,所以直接討論就好 m 1 時 是前 k 個最大連續欄位和 定義 f ...

P2331 SCOI2005 最大子矩陣

傳送門 首先感謝ccsc友 xi 好 zhi 的講解 康康m的範圍 m只能取1或者2 先看m 1 是一條鏈 那麼對於第i個點有三種情況 1 和上面連在一起成乙個矩陣 2 和下面連在一起成乙個矩陣 3 成為斷點 同樣的 對於m 2我們也這樣分析 設f i j k 代表第i行取了j個矩陣屬於第k種情況 ...

2331 SCOI2011 地板 插頭DP

國際慣例的題面 十分顯然的插頭dp。由於r c 100,所以min r,c 10,然後就可以愉悅地狀壓啦。我們用三進製狀壓,0表示沒有插頭,1表示有乙個必須延伸至少一格且拐彎的插頭,2表示有乙個必須延伸一格且不可以拐彎的插頭。轉移的話就十分顯然了。00 22,表示用這個格仔作為開始的拐角。00 10...