HDU6787
题意可转换为,
n
n
n个格子排成一列,恰好填入
m
m
m个传送器的方案数量。
要求:
- 放置的传送器最大的连续数量 ≤ 11 \leq 11 ≤11个
- 1 1 1号和 n n n号格子不能放传送器
- 传送器传送到的位置 j < j< j<传送器所在的位置 i i i
Solution
首先要发现这是一个DP。
DP的条件:
- 无后效性
- 最优子结构
这道题满足DP的基本条件。(mod1e9+7 大概率计数dp )
(然后我是猜了一下复杂度来确定大概是个三维的DP)
DP解题步骤:
-
确定状态: d p [ i ] [ j ] [ k ] dp[i][j][k] dp[i][j][k]表示第 i i i个格子,已经放了 j j j个传送器,当前格子连续有 k k k个格子有传送器。
-
确定递推关系:
- k > 0 : d p [ i ] [ j ] [ k ] = ( d p [ i ] [ j ] [ k ] + d p [ i − 1 ] [ j − 1 ] [ k − 1 ] ∗ ( i − 1 ) ) % m o d k>0:dp[i][j][k]=(dp[i][j][k]+dp[i-1][j-1][k-1]*(i-1))\%mod k>0:dp[i][j][k]=(dp[i][j][k]+dp[i−1][j−1][k−1]∗(i−1))%mod
- k = 0 : d p [ i ] [ j ] [ 0 ] = ( d p [ i ] [ j ] [ 0 ] + d p [ i − 1 ] [ j − 1 ] [ k ] ) % m o d k=0:dp[i][j][0]=(dp[i][j][0]+dp[i-1][j-1][k])\%mod k=0:dp[i][j][0]=(dp[i][j][0]+dp[i−1][j−1][k])%mod
-
初始化: d p [ 1 ] [ 0 ] [ 0 ] = 1 dp[1][0][0]=1 dp[1][0][0]=1
-
确定边界
复杂度 O ( T n 2 k ) O(Tn^2k) O(Tn2k)
Code
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const double eps = 1e-8;
const int NINF = 0xc0c0c0c0;
const int INF = 0x3f3f3f3f;
const ll mod = 1e9 + 7;
const ll N = 1e3 + 5;
int n,m,f[N][N][11];
void solve(){
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=0;j<=min({i-1,m,n-2});j++)
for(int k=0;k<=10;k++)
f[i][j][k]=0;
f[1][0][0]=1;
for(int i=2;i<=n;i++)
for(int j=0;j<=min({i-1,m,n-2});j++)
for(int k=0;k<=min(j,10);k++){
f[i][j][0]=(f[i][j][0]+f[i-1][j][k])%mod;
if(k>0 and j>0) f[i][j][k]=(f[i][j][k]+1ll*f[i-1][j-1][k-1]*(i-1))%mod;
}
cout<<(f[n][m][0]?f[n][m][0]:-1)<<'\n';
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
int T;cin>>T;
while(T--) solve();
return 0;
}