洛谷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。先分析狀態數,會發現區域性極小值在一張圖...