状压dp 棋盘问题
棋盤問題1
問題描述
在n×n(n≤20)
的方格棋盤上放置n個車(可以攻擊所在行、列),求使它們不能互相攻擊的方案總數。
輸入格式
一行,若干個1到20之間的整數。
輸出格式
若干行,對于輸入的每個整數,輸出其方案數。
樣例輸入
3 2樣例輸出
6 2限制與約定
時間限制:1s
空間限制:128MB
#include<iostream> #include<cstring> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; long long f[1<<20]; int main() {int n;while(scanf("%d",&n)==1){memset(f,0,sizeof(f));f[0]=1;for(long long i=1;i<=(1<<n);i++)for(long long t=i;t>0;t-=t&-t)f[i]+=f[i&~(t&-t)]; cout<<f[(1<<n)-1]<<endl;}return 0; }棋盤問題2
問題描述
在 n×n(n≤20)
的方格棋盤上放置n 個車(可以攻擊所在行、列),某些格子不能放,求使它們不能互相攻擊的方案總數。
輸入格式
給你一個n和m,分別表示棋盤的大小,不能放的格子總數。接下來是m行坐標,表示不能放置的位子。
輸出格式
符合條件的方案總數。
輸入樣例1
3 2 1 2 2 3輸出樣例1
3輸入樣例2
4 1 1 1輸出樣例2
18限制與約定
時間限制:1s
空間限制:128MB
#include<iostream> #include<cstring> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; long long f[1<<20],s[25]; int main() {int n,m;while(scanf("%d%d",&n,&m)!=EOF){memset(f,0,sizeof(f));memset(s,0,sizeof(s));for(int i=0,a,b;i<m;i++){cin>>a>>b;s[a]+=1<<(b-1);}f[0]=1;for(long long i=1;i<=(1<<n);i++){int num=0;for(long long t=i;t>0;t-=t&-t) num++;for(long long t=i;t>0;t-=t&-t)if(!(s[num]&(t&-t)))f[i]+=f[i&~(t&-t)];}cout<<f[(1<<n)-1]<<endl;}return 0; }棋盤問題3
問題描述
給出一個n×m
的棋盤(n、m≤80,n×m≤80
),要在棋盤上放k(k≤20)個棋子, 使得任意兩個棋子不相鄰(相鄰指上下左右四個方向)。求可以放置的總的方案數。
輸入格式
一行三個整數n,m,k,表示棋盤大小為n行m列,棋盤上放置k個棋子。
輸出格式
一個整數表示方案數。
輸入樣例1
3 3 2輸出樣例1
24輸入樣例2
2 2 2輸出樣例2
2輸入樣例3
20 1 2輸出樣例3
171限制與約定
時間限制:1s
空間限制:128MB
?
#include<iostream> #include<cstring> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; long long num,f[21][1<<9][21],s[1<<10],c[1<<10],n,m,kl; void dfs(int ans,int pos,int flag) {if(pos>m){s[++num]=ans;c[num]=flag;return;}dfs(ans,pos+1,flag);dfs(ans+(1<<pos-1),pos+2,flag+1); } int main() {while(scanf("%lld%lld%lld",&n,&m,&kl)!=EOF){if(n<m) swap(n,m);memset(f,0,sizeof(f));num=0;dfs(0,1,0);for(int i=1;i<=num;i++)f[1][s[i]][c[i]]=1;for(long long i=2;i<=n;i++)for(long long j=1;j<=num;j++)for(long long l=1;l<=num;l++)if(!(s[l]&s[j]) )for(int k=0;k<=kl;k++)if(k>=c[j]) f[i][s[j]][k]+=f[i-1][s[l]][k-c[j]];long long ans=0;for(int i=1;i<=num;i++)ans+=f[n][s[i]][kl];cout<<ans<<endl;}return 0; }棋盤問題4
問題描述
在n×n(n≤10)
的棋盤上放k 個國王(可攻擊相鄰的8 個格子),求使它們無法互相攻擊的方案數。
輸入格式
一行兩個整數n,k,棋盤大小為n行n列,棋盤上放置k個棋子。
輸出格式
一個整數表示方案數。
輸入樣例1
2 1輸出樣例1
4輸入樣例2
3 2輸出樣例2
16限制與約定
時間限制:1s
空間限制:128MB
#include<iostream> #include<cstring> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; long long num,f[11][1<<10][15],s[1<<11],c[1<<11],n,kl; void dfs(int ans,int pos,int flag) {if(pos>n){s[++num]=ans;c[num]=flag;return;}dfs(ans,pos+1,flag);dfs(ans+(1<<pos-1),pos+2,flag+1); } int main() {while(scanf("%lld%lld",&n,&kl)!=EOF){memset(f,0,sizeof(f));num=0;dfs(0,1,0);for(int i=1;i<=num;i++)f[1][s[i]][c[i]]=1;for(long long i=2;i<=n;i++)for(long long j=1;j<=num;j++)for(long long l=1;l<=num;l++)if(!(s[l]&s[j]) && !((s[l]<<1) & s[j]) && !((s[l]>>1)&s[j]))for(int k=0;k<=kl;k++)if(k>=c[j]) f[i][s[j]][k]+=f[i-1][s[l]][k-c[j]];long long ans=0;for(int i=1;i<=num;i++)ans+=f[n][s[i]][kl];cout<<ans<<endl;}return 0; }?
轉載于:https://www.cnblogs.com/hfang/p/11239848.html
總結
- 上一篇: Linux C语言错误处理
- 下一篇: 二分 划分数列