[JZOJ5398]:Adore(状压DP+记忆化搜索)

Posted wzc521

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[JZOJ5398]:Adore(状压DP+记忆化搜索)相关的知识,希望对你有一定的参考价值。

题目描述

  小$w$偶然间见到了一个$DAG$。
  这个$DAG$有$m$层,第一层只有一个源点,最后一层只有一个汇点,剩下的每一层都有$k$个节点。
  现在小$w$每次可以取反第$i(1<i<n-1)$层和第$i+1$层之间的连边。也就是把原本从$(i,k_1)$连到$(i+1,k_2)$的边,变成从$(i,k_2)$连到$(i+1,k_1)$。
  请问他有多少种取反的方案,把从源点到汇点的路径数变成偶数条?
  答案对$998244353$取模。


输入格式

  一行两个整数$m,k$。
  接下来$m-1$行,第一行和最后一行有$k$个整数$0$或$1$,剩下每行有$k^2$个整数$0$或$1$,第$(j-1) imes k+t$个整数表示$(i,j)$到$(i+1,t)$有没有边。


输出格式

  一行一个整数表示答案。


样例

样例输入:

5 3
1 0 1
0 1 0 1 1 0 0 0 1
0 1 1 1 0 0 0 1 1
0 1 1

样例输出:

4


数据范围与提示

  $20\%$的数据满足$nleqslant 10,kleqslant 2$。
  $40\%$的数据满足$nleqslant 10^3,kleqslant 2$。
  $60\%$的数据满足$mleqslant 10^3,kleqslant 5$。
  $100\%$的数据满足$4leqslant mleqslant 10^4,kleqslant 10$。


题解

发现$k$很小,考虑状压$DP$,设$dp[i][s]$表示第$i$行,能连边的点的状态为$s$的方案数。

转移用记忆化搜索即可,从后往前搜索。

时间复杂度:$Theta(NK2^K)$。

期望得分:$100$分。

实际得分:$100$分。


代码时刻

#include<bits/stdc++.h>
using namespace std;
const int mod=998244353;
int M,K,S;
int Map[2][10001][11],a[11],g[1025];
long long dp[10001][1025];
int lowbit(int x){return x&-x;}
long long dfs(int x,int s)
{
	if(dp[x][s]!=-1)return dp[x][s];
	if(x==2)
	{
		dp[x][s]=1;
		for(int i=1;i<=K;i++)dp[x][s]^=a[i]&((s&(1<<(i-1)))!=0);
	}
	else
	{
		int ls=0,rs=0;
		for(int i=1;i<=K;i++)
		{
			ls|=g[Map[0][x-1][i]&s]<<(i-1);
			rs|=g[Map[1][x-1][i]&s]<<(i-1);
		}
		dp[x][s]=(dfs(x-1,ls)+dfs(x-1,rs))%mod;
	}
	return dp[x][s];
}
int main()
{
	memset(dp,-1,sizeof(dp));
	scanf("%d%d",&M,&K);
	for(int i=1;i<(1<<K);i++)g[i]=g[i-lowbit(i)]^1;
	for(int i=1;i<=K;i++)scanf("%d",&a[i]);
	for(int i=2;i<M-1;i++)
		for(int j=1;j<=K;j++)
			for(int k=1;k<=K;k++)
			{
				int x;scanf("%d",&x);
				Map[0][i][j]|=x<<(k-1);
				Map[1][i][k]|=x<<(j-1);
			}
	for(int i=1;i<=K;i++)
	{
		int x;
		scanf("%d",&x);
		S|=x<<(i-1);
	}
	printf("%lld",dfs(M-1,S));
	return 0;
}

rp++

以上是关于[JZOJ5398]:Adore(状压DP+记忆化搜索)的主要内容,如果未能解决你的问题,请参考以下文章

UVA - 10817 Headmaster's Headache (状压dp+记忆化搜索)

JZOJ 3747(状压DP)

ACM - 动态规划小白入门:背包 / 线性 / 区间 / 计数 / 数位统计 / 状压 / 树形 / 记忆化 DP

LeetCode 944. 删列造序 / 面试题 01.05. 一次编辑 / 691. 贴纸拼词(记忆化搜索+状压dp)

jzoj1340状压DP周长

jzoj5990. 北大2019冬令营模拟2019.1.6Bear (状压dp)