• [CSP-S模拟测试]:y(DP+bitset)


    题目背景

    $frac{1}{4}$遇到了一道水题,叕完全不会做,于是去请教小$D$。小$D$懒得理$frac{1}{4}$,直接就离开了。于是,$frac{1}{4}$只好来问你,这道题是这样的:


    题目描述

    给定一个无向图,$n$个点(从$1$开始编号)、$m$条边(长度为$1$),每条边有一个权值$c(cin{0,1})$。
    一条路径,可以表示为一个长度为经过边数的$01$串,串的第$i$位为经过的第$i$条边的权值。
    两条路径相同,当且仅当表示其的$01$串相同。
    求从$1$号点出发、长度为$d$的路径种数。


    输入格式

    从文件$y.in$中读入数据。
    第一行,三个整数,$n,m,d$。
    接下来$m$行,每行三个整数$u,v,c$,代表一条边连接$u$和$v$,权值为$c$。


    输出格式

    输出到文件$y.out$中。
    输出一行,一个整数,代表答案。


    样例

    样例输入:

    3 2 3
    1 2 0
    1 3 1

    样例输出:

    4


    数据范围与提示

    样例解释:

    $1 ightarrow 2 ightarrow 1 ightarrow 2Rightarrow 000$
    $1 ightarrow 2 ightarrow 1 ightarrow 3Rightarrow 001$
    $1 ightarrow 3 ightarrow 1 ightarrow 2Rightarrow 110$
    $1 ightarrow 3 ightarrow 1 ightarrow 3Rightarrow 111$

    数据范围:

    保证$nin [1,90],min [0,n imes (n−1)],din [1,20],u,vin [1,n],cin{0,1}$。


    题解

    考虑$DP$,设$dp[i][j][stack]$表示从$i$到$j$是否有一条状态为$stack$的连边。

    那么显然时间复杂度是:$Theta(s^d imes n imes (n+m))$的。

    考虑第一个优化,使用$bitset$,我们能够优化掉$j$那一维。

    但是时间复杂度还是不够,于是我们考虑$meet in the middle$算法,只算前一半即可。

    时间复杂度:$Theta(2^{frac{d}{2}} imes n imes (n+m)+2^d imes n)$。

    期望得分:$100$分。

    实际得分:$100$分。


    代码时刻

    #include<bits/stdc++.h>
    using namespace std;
    int n,m,d;
    bitset<90> bit[4][1100000];
    long long ans;
    int main()
    {
    	scanf("%d%d%d",&n,&m,&d);
    	for(int i=1;i<=m;i++)
    	{
    		int u,v,c;
    		scanf("%d%d%d",&u,&v,&c);
    		if(c)bit[1][u][v]=bit[1][v][u]=1;
    		else bit[0][u][v]=bit[0][v][u]=1;
    	}
    	int dis=(d+1)>>1;
    	for(int i=n;i;i--)
    	{
    		for(int j=0;j<(1<<d);j++)bit[2][j].reset();
    		bit[2][1][i]=1;
    		for(int j=1;j<(1<<dis);j++)
    			for(int k=1;k<=n;k++)
    			{
    				if(!bit[2][j][k])continue;
    				bit[2][j<<1]|=bit[0][k];
    				bit[2][j<<1|1]|=bit[1][k];
    			}
    		for(int j=0;j<(1<<dis);j++)
    			bit[3][j][i]=bit[2][(1<<dis)|j].count()?1:0;
    	}
    	for(int i=0;i<(1<<dis);i++)
    		for(int j=0;j<(1<<(d-dis));j++)
    			if(((bit[3][i]&bit[2][(1<<(d-dis))|j]).count()))ans++;
    	printf("%lld",ans);
    	return 0;
    }
    

    rp++

  • 相关阅读:
    #ifndef 、 #define 、#endif使用解释
    基于小熊派Hi3861鸿蒙开发的IoT物联网学习【六】--智慧农业MQTT数据上传华为云
    C语言学习(三)
    c语言学习篇二【基础语法】
    简单图解OSI七层网络模型
    基于小熊派Hi3861鸿蒙开发的IoT物联网学习【五】
    使用Doxygen生成html/chm范例,方便源码阅读
    李宏毅《深度学习》P1----机器学习介绍
    keras实现Alexnet (cifar10数据集)
    cmake条件编译
  • 原文地址:https://www.cnblogs.com/wzc521/p/11606517.html
Copyright © 2020-2023  润新知