Gym 102219 F Military Class —— 记忆化搜索

202 篇文章 5 订阅

This way

题意:

现在有两列士兵,第一列的第i个人可以与第二列的第i-e到第i+e的人匹配。但是有一些人不能相互匹配。问你有多少种匹配方法。

题解:

首先数据范围是2000,那么第一个想到的是区间DP,但是不对,因为它没有办法分割成多个区间。然后看见它的e是4,应该是个状压dp。那么久可以设dp[i][s]表示到第i个人的时候,它可以匹配的位置的状态是s的时候,答案的个数。然后由于它是枚举e来搜索的,那么前面的状态必然用到多次后面的状态,所以应该是记忆化搜索。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll mod=1e9+7;
const int N=2e3+5;
ll dp[N][(1<<9)+5];
bool mp[N][N];
int n,e,k,x,y;
ll dfs(int pos,int s){
    if(pos>n)
        return 1;
    s>>=1;
    if(~dp[pos][s])
        return dp[pos][s];
    ll ans=0;
    for(int i=0;i<=e*2;i++){
        if(pos-e+i>=1&&pos-e+i<=n&&!(s&(1<<i))&&!mp[pos][pos-e+i]){
            int ne=s|(1<<i);
            ans=(ans+dfs(pos+1,ne))%mod;
        }
    }
    dp[pos][s]=ans;
    return ans;
}
int main()
{
    memset(dp,-1,sizeof(dp));

    scanf("%d%d%d",&n,&e,&k);
    for(int i=1;i<=k;i++)
        scanf("%d%d",&x,&y),mp[x][y]=1;
    printf("%lld",dfs(1,0));
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值