首页 > 其他分享 >【XSY3270】Domino Colorings(轮廓线dp,状压)

【XSY3270】Domino Colorings(轮廓线dp,状压)

时间:2022-10-30 11:13:55浏览次数:55  
标签:ch int Domino 状压 ans 轮廓线 Colorings dp mod

若已经知道了每个格子的颜色,我们可以用轮廓线 DP(类似插头 DP)判断棋盘是否能被多米诺骨牌填满,设 \(dp[S]\) 表示是否存在某种填法使得轮廓线每个位置是否被填的状态为 \(S\) 即可。

现在我们需要枚举每个格子的颜色,同时还要判断能否被填,所以我们要记录一维表示 \(dp[S]\) 数组。

为了转移时维护这一数组,我们还要记录轮廓线上每个格子的颜色。

于是设 \(f(i,j,c,s)\) 表示考虑到 \((i,j)\),轮廓线上格子颜色的状压为 \(c\),\(dp[S]\) 数组的状压为 \(s\) 的方案数。

有点像 DP 套 DP(

至于为什么 \(f(i,j)\) 的状态数可以接受:

如图,假设 \((i,j)\) 是当前的箭头所指的格子,那么轮廓线就是图中红框区域:(我把整个棋盘横竖交换了,这样我习惯些)

在这里插入图片描述

对于某种 \((c,s)\) 来说,假如如图的多米诺骨牌填法满足 \((c,s)\) 的限制:

在这里插入图片描述

那么绿框部分的颜色和填法是不受 \((c,s)\) 影响的,只要能填满就行。

换言之,无论 \((c,s)\) 怎么取,如图框起来的绿色部分是不受 \((c,s)\) 影响的,或者说 \((c,s)\) 并没有记录绿框内填牌的状态:

在这里插入图片描述

又由于一种填色方案只对着一种 \((c,s)\),所以 \((c,s)\) 的状态数顶多是黄框内的格子的颜色的状态数,即 \(2^{2n}=2^{12}=4096\) 种。

实际上的状态数肯定是比我们讨论的这个还小的,solution 实测说是 \(2000\) 多种。

时间复杂度 \(O(nm2^{2n}\log 2^{2n})=O(n^2m2^{2n})\)。

#include<bits/stdc++.h>

#define ull unsigned long long

using namespace std;

namespace modular
{
	const int mod=1000000007;
	inline int add(int x,int y){return x+y>=mod?x+y-mod:x+y;}
	inline int dec(int x,int y){return x-y<0?x-y+mod:x-y;}
	inline int mul(int x,int y){return 1ll*x*y%mod;}
	inline void Add(int &x,int y){x=(x+y>=mod?x+y-mod:x+y);}
}using namespace modular;

inline int poww(int a,int b)
{
	int ans=1;
	while(b)
	{
		if(b&1) ans=mul(ans,a);
		a=mul(a,a);
		b>>=1;
	}
	return ans;
}

inline int read()
{
	int x=0,f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9')
	{
		if(ch=='-') f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9')
	{
		x=(x<<1)+(x<<3)+(ch^'0');
		ch=getchar();
	}
	return x*f;
}

struct data
{
	int col;
	ull sta;
	data(){};
	data(int a,ull b){col=a,sta=b;}
};

bool operator < (data a,data b)
{
	if(a.col==b.col) return a.sta<b.sta;
	return a.col<b.col;
}

int n,m,maxS;

map<data,int>f[2];

int main()
{
	n=read(),m=read();
	maxS=(1<<n)-1;
	int u=1,v=0;
	f[u][data(0,1)]=1;
	for(int i=1;i<=m;i++)
	{
		for(int j=0;j<n;j++,swap(u,v))
		{
			f[v].clear();
			for(map<data,int>::iterator it=f[u].begin();it!=f[u].end();it++)
			{
				int c=(it->first).col;
				ull dps=(it->first).sta;
				ull ndps0=0,ndps1=0;
				for(int s=0;s<=maxS;s++) 
				{
					if((dps>>s)&1)
					{
						if((s>>j)&1)//上面没填 
						{
							if((c>>j)&1) ndps0|=(1ull<<(s^(1<<j)));
							else ndps1|=(1ull<<(s^(1<<j)));
						}
						else
						{
							if(j>0&&((s>>(j-1))&1))//跟左边填
							{
								if((c>>(j-1))&1) ndps0|=(1ull<<(s^(1<<(j-1))));
								else ndps1|=(1ull<<(s^(1<<(j-1))));
							}
							ndps0|=(1ull<<(s^(1<<j))),ndps1|=(1ull<<(s^(1<<j)));//跟下面填 
						}
					}
				}
				Add(f[v][data((c|(1<<j))^(1<<j),ndps0)],it->second);
				Add(f[v][data(c|(1<<j),ndps1)],it->second);
			}
		}
	}
	int ans=0;
	for(map<data,int>::iterator it=f[u].begin();it!=f[u].end();it++)
	{
		ull s=(it->first).sta;
		if(s&1) Add(ans,it->second);
	}
	printf("%d\n",ans);
	return 0;
}

标签:ch,int,Domino,状压,ans,轮廓线,Colorings,dp,mod
From: https://www.cnblogs.com/ez-lcw/p/16840745.html

相关文章

  • 【XSY2444】【BZOJ4042】【CERC2014】【luogu4757】Parades(树形dp+状压dp)
    题面Description从前有个A国,它有\(n\)个城市和\(n-1\)条道路。每条路连接两个城市。城市之间两两可达。每个城市与不超过10条道路相连。现在给出\(m\)条路径,要求从这些......
  • AGC017F Zigzag【状压 DP】
    传送门以下认为\(n,m\)同阶。首先,我们可以根据每次走的方向用一个二进制数来表示一条折线。这样显然有一个傻逼DP,设\(f_{i,S}\)表示已经确定了前\(i\)条折线,其中......
  • 状压dp
    状压dp[SCOI2005]互不侵犯题目描述在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个......
  • 【题解】CF11D A Simple Task(状压 DP)
    【题解】CF11DASimpleTask题目链接CF11DASimpleTask题意概述给定一张\(n\)个点\(m\)条边的无向图,无重边自环,点数不超过\(19\),求无向图中环的数量。思路分......
  • 状压DP
    [POI1997]Genotype题目背景Genotype是一个独特的基因串。题目描述我们可以用大写英文字母$A-Z$来描述Genotype,每个字母就代表一个基因。规定一种「分裂」规则,由......
  • 状压dp刷题记录【持续更新】
    前言:许多算法的状态数并不支持其在多项式时间内运行完成。比如TSP问题这种大部分为NP-Hard的问题。在数据范围缩小的前提下(例如\(n\leq21\)),不妨将状态数压缩成二进制情......
  • 【题解】P2167 [SDOI2009]Bill的挑战(状压 DP)
    【题解】P2167[SDOI2009]Bill的挑战挺好的一道状压DP。可惜我脑子有病。()题目链接P2167[SDOI2009]Bill的挑战](https://www.luogu.com.cn/problem/P3225)题意概述......
  • Arrange the Bulls(状压dp)
    ArrangetheBulls(状压dp)题目大意:一些牛喜欢一些地方(每头牛都有一些喜欢的地方),现在要把这些地方分配给牛,每头牛都应该分到一个地方,问有多少种分配的方法此题拥有着状压d......
  • P5911 [POI2004]PRZ——状压dp
    一样,从\(n\le16\)启发用状压dp思路本质上与UVA11825Hackers'Crackdown异曲同工,不过可以通过预处理处理出一组人的集合时间复杂度最坏为\(O(2^{2n})\),当任何一个集合......
  • P2622 关灯问题II——状压dp
    本题是一道十分好的状压dp练手题基本思路初看这道题时其实并没有什么思路,在看到\(n\le10\)时才想到使用状压dp有时候搜索时间复杂度很高,也没有方法优化到多项式复杂度,......