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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

【dfs】飞行棋

發(fā)布時間:2023/12/3 编程问答 57 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【dfs】飞行棋 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

題目大意

給你一個n*m的網格,現(xiàn)在讓你往里面填1~k(有的位置已經填了),使其滿足所有從(1,1)到(n,m)的路徑不會經過相同的數(shù)字(只能往下或往右),求方案數(shù)


解題思路

對于k<n+m-1的,無法填滿任意一條路徑,特判掉

然后考慮dfs

每個位置只填左上矩陣和右下矩陣沒填過的數(shù)(保證不重),且如果當前位置剩余顏色小于到終點的距離,那么直接特判

對于自由填的顏色(輸入沒填過),考慮到某些方案只是將顏色轉換了一下,那么讓自由填的顏色從小到大填,然后乘排列數(shù)


code

#include<bitset> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define ll long long #define N 12 #define wyc 1000000007 using namespace std; ll n,m,k,ls,ans,num,g[N],a[N][N],p[N],nx[N]; bitset<N>sum[N][N],summ[N][N]; void dfs(ll x,ll y,ll now,ll gg) {if(x>n||y>m){(ans+=g[gg])%=wyc;;return;}if(a[x][y]){if(summ[x-1][y][a[x][y]]||summ[x][y-1][a[x][y]]||sum[x+1][y][a[x][y]]||sum[x][y+1][a[x][y]])return;summ[x][y]=summ[x-1][y]|summ[x][y-1];summ[x][y].set(a[x][y],1);if(n-x+m-y>k-summ[x][y].count())return;dfs(x+y/m,y%m+1,now,gg);return;}for(ll i=1;i<=k;++i)if(p[i]||i<=now){if(summ[x-1][y][i]|| summ[x][y-1][i]||sum[x+1][y][i]||sum[x][y+1][i])continue;summ[x][y]=summ[x-1][y]|summ[x][y-1];summ[x][y].set(i,1);if(n-x+m-y>k-summ[x][y].count())return;if(i==now)dfs(x+y/m,y%m+1,nx[now],gg+1);else dfs(x+y/m,y%m+1,now,gg);}return; } int main() {scanf("%lld%lld%lld",&n,&m,&k);if(n+m-1>k){puts("0");return 0;}for(ll i=1;i<=n;++i)for(ll j=1;j<=m;++j)scanf("%lld",&a[i][j]);for(ll i=n;i>0;--i)for(ll j=m;j>0;--j)if(a[i][j]){sum[i][j]|=sum[i][j+1]|sum[i+1][j];if(sum[i][j][a[i][j]]){puts("0");return 0;}sum[i][j].set(a[i][j],1);p[a[i][j]]=1;}ls=k+1;for(ll i=k;i>0;--i)if(!p[i]){num++;nx[i]=ls;ls=i;}g[0]=1;for(int i=1;i<=num;++i)g[i]=g[i-1]*(num-i+1);dfs(1,1,ls,0);printf("%lld",ans);return 0; }

總結

以上是生活随笔為你收集整理的【dfs】飞行棋的全部內容,希望文章能夠幫你解決所遇到的問題。

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