zoukankan      html  css  js  c++  java
  • [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++

  • 相关阅读:
    计算机网络中的多路复用技术
    ActiveMQ之一--ActiveMQ入门
    ehcache介绍
    I/O模型之二:Linux IO模式及 select、poll、epoll详解
    【甘道夫】HBase(0.96以上版本号)过滤器Filter具体解释及实例代码
    Android Studio安装及主题字体配置
    HDU 2136 Largest prime factor 參考代码
    update更新两个字段
    Hadoop对小文件的解决方式
    赵雅智_ContentProvider
  • 原文地址:https://www.cnblogs.com/wzc521/p/11832842.html
Copyright © 2011-2022 走看看