题意:m根柱子平行摆放,间距为1,每根柱子的高度都为n+1.
可以在两根柱子之间的某个刻度[1,2....n]上连接一条线(不能斜着,并且每一条连接的线都没有共同的端点)
起点为(1,1) 每次往下走,只到遇到直线 则朝该条直线的方向上走.
1<=n<=100. 1<=m<=8. 给出k,问有多少种连续方案使得能从起点走到(n+1,k).
因为每条直线都没有共同的端点, 说明不能连续向左或者向右,
以行为层次来DP.每做一次决策就往下一行. (这样决策变为三种:左右,以及不动.)
设dp[i][j]为有多少种画线方案,使得从(0,0)出发到达(i,j).
dp[i+1][k] = Σ dp[i][j] *num[j][k] . [num[j][k]为每一行有多少种画线方案使得在第j列能到第k列, 2^m次暴力预处理即可.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> ii;
const int N=2e2+5,mod=1e9+7;
ll n,m,k,dp[N][N],num[N][N];
int main(){
ios::sync_with_stdio(false);cin.tie(0);
cin>>n>>m>>k;
for(int s=0;s<(1<<(m-1));s++){
bool ok=true;
for(int j=0;j<m-1;j++){
int b1=(s>>j)&1;
int b2=(s>>(j+1))&1;
if(b1==b2&&b1) ok=false;
}
if(!ok) continue;
for(int j=0;j<m;){
if((s>>j)&1){
num[j][j+1]++,num[j+1][j]++;
j+=2;
}
else{
num[j][j]++;
j++;
}
}
}
dp[0][0]=1;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
for(int p=0;p<m;p++) dp[i+1][p]=(dp[i+1][p]+(dp[i][j]*num[j][p])%mod)%mod;
cout<<dp[n][k-1]<<'\n';
return 0;
}