bzoj 2669 區域性極小值
有乙個n行m列的整數矩陣,其中1到nm之間的每個整數恰好出現一次。如果乙個格仔比所有相鄰格仔(相鄰是指有公共邊或公共頂點)都小,我們說這個格仔是區域性極小值。
給出所有區域性極小值的位置,你的任務是判斷有多少個可能的矩陣。
有乙個和dp求n的排列中有k個逆序對的方案數一樣的轉化
從小到大放數,那麼如果乙個是區域性極小值的格仔沒有被放數,那麼周圍都不能放數。由於最多有8個位置是區域性極小值,所以可以狀壓哪些格仔放了。
令cnt[s]表示當前狀態已經被放了區域性極小值的格仔的總數和不是區域性極小值的格仔中可以放的格仔的總和。f[s][i]表示狀態為s,放了前i個數的方案數。那麼f[s][i]=sigma(f[s^j][i-1](j&s>0))+[cnt[s]-(i-1)]*f[s][i-1]
然後會有一些不是區域性極小值的位置出現了區域性最小值,容斥掉就行了
#include#include
#include
#include
#include
#define ll long long
#define inf 1e9
#define eps 1e-10
#define md 12345678
#define n 1010
using namespace std;
bool mp[6][9],ok[6][9];
int cnt[n];
ll f[1010][100];
int n,m,mxn; ll ans=0;
char st[110];
struct point q[100];
int lx[8]=,ly[8]=;
ll solve()
;for (int s=0;s<(1<>e)&1))
} else cnt[s]++;
}for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
if ((!ok[i][j]&&(!mp[i][j]))) cnt[s]++;
}//printf("cnt: "); for (int i=0;i<(1<0) f[s][i]=(f[s][i]+f[s][i-1]*(cnt[s]-(i-1))%md)%md;
if (f[s][i]==0) continue;
for (int j=0;j>j)&1)) f[s|(1dfs(mxn+1,s);
for (int now=dep;now<=mxn;now++)
}if (ok)}}
}void check()}}
}}int main()
check();
dfs(1,0);
printf("%d\n",ans);
return 0;
}
BZOJ2669 區域性極小值
題目 有乙個n行m列的整數矩陣,其中1到nm之間的每個整數恰好出現一次。如果乙個格仔比所有相鄰格仔 相鄰是指有公共邊或公共頂點 都小,我們說這個格仔是區域性極小值。給出所有區域性極小值的位置,你的任務是判斷有多少個可能的矩陣。思路看到資料範圍馬上想到狀壓dp。先分析狀態數,會發現區域性極小值在一張圖...
bzoj2669 CQOI2012 區域性極小值
洛谷bzoj 這道題的方法是用dfs進行搜尋容斥時,dp統計答案 感覺痛苦的同學建議做做 乙個區域性最小值就可以覆蓋最少四個點 放在四個角上 最多九個 放在中間 所以最多隻會有8個區域性最小值,可以考慮一下狀壓 我們可以考慮從小到大地放入每個元素 dp i j 表示在選擇的區域性最小值狀態為j時,已...
bzoj2669 cqoi2012 區域性極小值
題目鏈結 給出乙個 n m 的整數矩陣,其中 1,nm 中的整數每個出現一次,有一些位置為區域性最小值。問方案數。好神的dp啊。cnt j 表示的是,在區域性最小值被填充的狀態為 j 的情況下,目前有多少個位置可以填,這些位置中包括已經被填了數的位置。最後加模再取模 bzoj2669 include...