HDU 6787 Chess (dp)

程序设计大赛策略解析

链接: 2020 年百度之星·程序设计大赛 - 初赛三 1005

在这里插入图片描述
题意:
有一个长度为 n 的棋盘,你每次扔筛子可以向前移动 1-11格,你还可以在棋盘上设置 m 个传送器,传送到当前位置以前的位置,问有多少种传送器的摆放方式,使你可以到达 n 点。
思路:

  1. 分析一下什么情况下不能达到 n 点 ,因为传送器只能往前传,所以当这里有大于连续 10 个传送器时,他就无法到达 n 点。
  2. 所以可以设置 dp 状态为 dp[ i ][ j ][ k ],表示到第 i 个位置摆放了 j 个传送器 ,并且有 k 个连续的传送器的方案数。然后转移就很好写了。
  3. 开 ll 会爆内存 ,但 int 的话中间有个乘会超过 int 范围 ,所以用 ll 算一下在加 ,一次 dp 把所有答案都预处理出来,不用每次都算。
#include <iostream>
#include <cstdio>
#include <map>
#include <math.h>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 1e3 + 1;
const int mod=1e9+7;
int T,n,m;
int dp[maxn][maxn][11];
void solve(int n , int m){
    for(int i = 1; i <= n; i++) dp[i][0][0] = 1;
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= i; j++){
            for(int k = 0; k <= 10; k ++){
                dp[i][j][0] = (dp[i][j][0] + dp[i-1][j][k]) % mod;
                if(k < 10){
                    ll x = (ll)dp[i-1][j-1][k] * (i-1) % mod ;
                    dp[i][j][k+1] = (dp[i][j][k+1] + x) % mod;
                }
            }
        }
    }
}
int main(){
    scanf("%d",&T);
    solve(1000,1000);
    while(T--){
        scanf("%d%d",&n,&m);
        if(dp[n][m][0] == 0) cout<<-1<<endl;
        else cout<<dp[n][m][0]<<endl;
    }
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值