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

  • 相关阅读:
    16. 3Sum Closest
    17. Letter Combinations of a Phone Number
    20. Valid Parentheses
    77. Combinations
    80. Remove Duplicates from Sorted Array II
    82. Remove Duplicates from Sorted List II
    88. Merge Sorted Array
    257. Binary Tree Paths
    225. Implement Stack using Queues
    113. Path Sum II
  • 原文地址:https://www.cnblogs.com/wzc521/p/11606517.html
Copyright © 2011-2022 走看看