日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

P3160:局部极小值(容斥、状压)

發(fā)布時間:2023/12/3 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 P3160:局部极小值(容斥、状压) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

解析

又是一道我不會的容斥題
qwq
本題的一個關鍵性質:答案有解時,極小值不超過8個
所以可以對其進行狀壓

考慮從小到大填數(shù)
那么在極小值填完之前,它的八連通必然是不能填的

設計dpi,sdp_{i,s}dpi,s?表示從小到大填了i個數(shù),已經(jīng)填完的極小值狀態(tài)為s的方案數(shù)
不難作出轉移

但是這樣會統(tǒng)計一些不合法的方案!
有的非極小值可能由于周圍全是非極小值,又隨便填,導致成為了極小值
所以要扣去所有非極小值成為極小值的方案

方法就是dfs枚舉哪些非極小值成為極小值dp再按這些非極小值的個數(shù)的奇偶性進行容斥

代碼

//暴力 #include<bits/stdc++.h> using namespace std; const int mod=12345678; #define ll long long #define il inline il ll read(){ll x=0,f=1;char c=getchar();while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}while(isdigit(c)){x=x*10+c-'0';c=getchar();}return x*f; } int n,m; bool jd[20][20]; int a[20][20]; int dx[9]={0,0,-1,-1,-1,0,1,1,1},dy[9]={0,-1,-1,0,1,1,1,0,-1}; int ans; inline bool exi(int x,int y){return x>=1&&x<=n&&y>=1&&y<=m; } int x[50],y[50],tot,mi[50]; bool vis[12][12]; int dp[35][1050]; int num[1050]; int calc(){tot=0;for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){if(jd[i][j]){++tot;x[tot]=i;y[tot]=j;}}}for(int s=0;s<mi[tot];s++){memset(vis,0,sizeof(vis));num[s]=n*m;for(int i=1;i<=tot;i++){if(s&mi[i-1]) continue;int xx=x[i],yy=y[i];if(!vis[xx][yy]){vis[xx][yy]=1;num[s]--;}for(int k=1;k<=8;k++){int nx=xx+dx[k],ny=yy+dy[k];if(exi(nx,ny)&&vis[nx][ny]==0){vis[nx][ny]=1;num[s]--;}}}//printf("s=%d num=%d\n",s,num[s]);}memset(dp,0,sizeof(dp));dp[0][0]=1;for(int i=1;i<=n*m;i++){for(int s=0;s<mi[tot];s++){dp[i][s]+=1ll*dp[i-1][s]*max(num[s]-i+1,0)%mod;if(dp[i][s]>=mod) dp[i][s]-=mod;for(int k=1;k<=tot;k++){if((s&mi[k-1])==0) continue;dp[i][s]+=dp[i-1][s-mi[k-1]];if(dp[i][s]>=mod) dp[i][s]-=mod;}}}return dp[n*m][mi[tot]-1]; } void dfs(int x,int y,int o){if(x>n){/*for(int i=1;i<=n;i++){for(int j=1;j<=m;j++) printf("%d ",jd[i][j]);putchar('\n');}*/if(o&1){ans-=calc();if(ans<0) ans+=mod;}else{ans+=calc();if(ans>=mod) ans-=mod;}//printf("ans=%d\n\n",ans);return;}if(y>m){dfs(x+1,1,o);return;}dfs(x,y+1,o);if(!jd[x][y]){for(int i=1;i<=8;i++){int nx=x+dx[i],ny=y+dy[i];if(exi(nx,ny)&&jd[nx][ny]) return;}jd[x][y]=1;dfs(x,y+1,o+1);jd[x][y]=0;} } int main(){ #ifndef ONLINE_JUDGEfreopen("a.in","r",stdin);freopen("a.out","w",stdout);#endifmi[0]=1;for(int i=1;i<=28;i++) mi[i]=mi[i-1]<<1;n=read();m=read();char c;for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){scanf(" %c",&c);jd[i][j]=c=='X';}}for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){if(!jd[i][j]) continue;for(int k=1;k<=8;k++){int nx=i+dx[k],ny=j+dy[k];if(exi(nx,ny)&&jd[nx][ny]){printf("0");return 0;}}}}dfs(1,1,0);printf("%d\n",ans); } /**/

總結

以上是生活随笔為你收集整理的P3160:局部极小值(容斥、状压)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內容還不錯,歡迎將生活随笔推薦給好友。