[BZOJ5299][状压DP]CQOI2018解锁屏幕

版权声明:虽然博主很菜,但是还是请注明出处(我觉得应该没人偷我的博客) https://blog.csdn.net/qq_43346903/article/details/87875981

BZOJ5299

简单的状压DP
预处理i到j要经过哪些点然后简单转移

Code:

#include<bits/stdc++.h>
#define mod 100000007
using namespace std;
inline int read(){
	int res=0,f=1;char ch=getchar();
	while(!isdigit(ch)) {if(ch=='-') f=-f;ch=getchar();}
	while(isdigit(ch)) {res=(res<<1)+(res<<3)+(ch^48);ch=getchar();}
	return res*f;
}
const int N=1100005;
int we[35],n,m,px[35],py[35],lb[N];
int pre[35][35],f[N][23],ans;
inline void init(){
	we[0]=1;
	for(int i=1;i<=20;i++) we[i]=we[i-1]<<1;
	for(int i=1;i<we[20];i++) lb[i]=lb[i^(i&-i)]+1;
	for(int i=0;i<n;i++)
		for(int j=0;j<n;j++){
			pre[i][j]=we[i]|we[j];
			for(int k=0;k<n;k++){
				if(px[k]>max(px[i],px[j])||px[k]<min(px[i],px[j])) continue;
				if(py[k]>max(py[i],py[j])||py[k]<min(py[i],py[j])) continue;
				if((px[i]-px[j])*(py[i]-py[k])==(px[i]-px[k])*(py[i]-py[j])) pre[i][j]|=we[k];
			}
		}
}
int main(){
	init();
	n=read();
	for(int i=0;i<n;i++) px[i]=read(),py[i]=read();
	init();
	for(int i=0;i<n;i++) f[we[i]][i]=1;
	for(int i=1;i<=n;i++)
		for(int j=0;j<we[n];j++) if(lb[j]==i)
			for(int k=0;k<n;k++) if(f[j][k]){
				if(i>=4) ans=(ans+f[j][k]%mod)%mod;
				for(int l=0;l<n;l++) if(!(we[l]&j)&&lb[(j&pre[k][l])^pre[k][l]]==1) f[j|we[l]][l]=(f[j|we[l]][l]+f[j][k]%mod)%mod;
			}
	cout<<ans;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43346903/article/details/87875981