G选修的期末 状压dp 计数dp方案数

在这里插入图片描述
在这里插入图片描述
dp[i][j]=0 要么永远到不了 要么下一个还没轮到
dp[i][j]不为0 有方案能转移到
i状态 第k位没取 满足本位和上位之差<k

#include<bits/stdc++.h>
using namespace std;
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)

#define forn(i,n)  for(int i=0;i<n;i++)
#define rep(i,a,n) for(int i=a;i<=n;i++)
typedef long long ll;
const int maxn=5005;	//200堆 
const int INF=0x3f3f3f3f;
const ll inf=0x3f3f3f3f3f3f3f3f;
const int mod=1e9+7;

ll n,q,kk,ans=0;
ll v[20];
ll dp[1<<16][20];
int main(){
	cin>>n>>kk;
	forn(i,n){
		cin>>v[i];
	}
	for(int i=0;i<n;i++){ //从每一位开始都合法 
		dp[1<<i][i]=1;	//只取1位 合法状态   从0开始第i位为1 其余位为0 合法 
	}	//取1个数 1种方案 
	for(int i=0;i<(1<<n);i++){	//i状态 0未取  1取 
		for(int j=0;j<n;j++){	//上一位 
			for(int k=0;k<n;k++){	//本位 
				if( (abs(v[k]-v[j])>=kk) || ((1<<k)&i) || dp[i][j]==0) //本位被访问 1<<k 从0起第k位用1 验证i状态第k位是否被取
					//i状态上一位不合法 或 跟从起始位置过来的连不上
					continue;
				(dp[(1<<k) | i][k]+=dp[i][j])%=mod;	//i状态第k位为0未取 取成1 满足<k 能从A状态->B状态 且只有1种状态 
			}
		} 
	}
	for(int i=0;i<n;i++){	//全取了 最终位为i的方案数和 
		(ans+=dp[(1<<n)-1][i])%=mod;
	}
	cout<<ans<<endl;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值