bzoj2669 CQOI2012 區域性極小值

2021-08-29 03:55:30 字數 1584 閱讀 6927

洛谷bzoj

這道題的方法是用dfs進行搜尋容斥時,dp統計答案(感覺痛苦的同學建議做做)

乙個區域性最小值就可以覆蓋最少四個點(放在四個角上),最多九個(放在中間)

所以最多隻會有8個區域性最小值,可以考慮一下狀壓

我們可以考慮從小到大地放入每個元素

dp[i][j]表示在選擇的區域性最小值狀態為j時,已經選了i個數,此時的方案數

這張圖裡面x代表的是區域性最小值,紅色的代表已經被選擇了

那麼思考dp[i][j]應該從**轉移過來

如果這次選的不是區域性最小值,那麼思考可以選取哪些位置

所有的區域性最小值的位置已經不能放了

還未選取的區域性最小值周圍的所有位置也不能放

這個可以通過預處理每個狀態得出總共有多少個位置,記為cnt[j]

其他的點就都可以選取了,總共有n*m-cnt[j]-(i-1)個

所以轉移方程就是dp[i][j]+=dp[i−1][j]×(cnt[j]−i+1);

如果選取的是區域性最小值,那麼就列舉這次選的是第k個區域性最小值

轉移方程就是dp[i][j]+=dp[i-1][j^(1《然後我們來思考這樣乙個問題:

我們只保證了這幾個一定是區域性最小值,外面會不會有其他的區域性最小值呢?

所以統計的方案是有多餘的

考慮用容斥來解決這個問題

減去外面有乙個多餘的方案,再加上兩個多餘的方案,等等...也就是奇加偶減

用dfs來實現這個過程,最多能夠搜尋到2的8次方個狀態,所以複雜度是有保障的

跑得非常快

#includeusing namespace std;

const int mod=12345678;

int dx[9]=;

int dy[9]=;

int ans,n,m,posx[10],posy[10],cnt[100005],maxa,vis[5][10];

int dp[30][305];

char a[5][10];

int moc(int x)

int ***()

} }for(int i=0;i=1&&yy<=m&&!vis[xx][yy])

vis[xx][yy]=1,cnt[i]--;}}

} }dp[0][0]=1;

for(int i=1;i<=n*m;i++)

void dfs(int kind)

} }}int main()

dfs(1);

cout<

return 0;

}

bzoj2669 cqoi2012 區域性極小值

題目鏈結 給出乙個 n m 的整數矩陣,其中 1,nm 中的整數每個出現一次,有一些位置為區域性最小值。問方案數。好神的dp啊。cnt j 表示的是,在區域性最小值被填充的狀態為 j 的情況下,目前有多少個位置可以填,這些位置中包括已經被填了數的位置。最後加模再取模 bzoj2669 include...

bzoj 2669 區域性極小值

bzoj 2669 區域性極小值 有乙個n行m列的整數矩陣,其中1到nm之間的每個整數恰好出現一次。如果乙個格仔比所有相鄰格仔 相鄰是指有公共邊或公共頂點 都小,我們說這個格仔是區域性極小值。給出所有區域性極小值的位置,你的任務是判斷有多少個可能的矩陣。有乙個和dp求n的排列中有k個逆序對的方案數一...

BZOJ2669 區域性極小值

題目 有乙個n行m列的整數矩陣,其中1到nm之間的每個整數恰好出現一次。如果乙個格仔比所有相鄰格仔 相鄰是指有公共邊或公共頂點 都小,我們說這個格仔是區域性極小值。給出所有區域性極小值的位置,你的任務是判斷有多少個可能的矩陣。思路看到資料範圍馬上想到狀壓dp。先分析狀態數,會發現區域性極小值在一張圖...