首页 > 其他分享 >一类哈密顿路径/回路为背景的状压dp

一类哈密顿路径/回路为背景的状压dp

时间:2024-03-29 16:14:30浏览次数:35  
标签:哈密顿 int 状压 long Limit https dp define

https://codeforces.com/contest/1950/problem/G

在非连通图上找到一条包含点最多的路径,dp数组维护可达性

// Problem: G. Shuffling Songs
// Contest: Codeforces - Codeforces Round 937 (Div. 4)
// URL: https://codeforces.com/contest/1950/problem/G
// Memory Limit: 256 MB
// Time Limit: 3000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
using namespace std;
#define ll long long
//# define int long long
#define ull unsigned long long
#define pii pair<int,int>

#define baoliu(x, y) cout << fixed << setprecision(y) << x
#define endl  "\n"
#define debug1(x) cerr<<x<<" "
#define  debug2(x) cerr<<x<<endl
const int N = 2e5 + 10;
const int M = 1e6 + 10;
const int inf = 0x3f3f3f3f;
const int mod = 998244353;
const double eps = 1e-8;
int n, m;
int a[N];

void solve(){
	vector<string>v1;
	vector<string>v2;
		cin>>n;
	vector<vector<int>>w(n+1,vector<int>(n+1,0));
	
	for(int i=0;i<n;i++){
		string s1,s2;cin>>s1>>s2;
		v1.push_back(s1);
		v2.push_back(s2);
	}
	for(int i=0;i<n;i++){
		for(int j=i;j<n;j++){
			//if(j==i)continue;
			if(v1[i]==v1[j]||v2[i]==v2[j]){
				w[i][j]=1;w[j][i]=1;
			}
		}
	}
	// for(int i=0;i<n;i++){
		// for(int j=0;j<n;j++){
			// cerr<<w[i][j];
		// }
		// cerr<<endl;
	// }
	//寻找答案状态:枚举最终的状态和终点,从而计算答案
	int ans=0;
	vector<vector<int>>dp((1<<n)+1,vector<int>(n+1,0));
	//fill(dp[0].begin(),dp[0].end(),1);
	for(int i=0;i<n;i++)dp[1<<i][i]=1;
	for(int i=0;i<(1<<n);i++){
		for(int j=0;j<n;j++){
			int u=(i>>j)&1;
			if(u==0)continue;
			for(int k=0;k<n;k++){
				//为什么不能判断终点j和k转移重复
				//这会导致初始只有一个0基础态无法转移
				int v=(i>>k)&1;
				if(v==0)continue;
				int last=i-(1<<j);
	dp[i][j]|=dp[last][k]&w[k][j];
//	cerr<<i<<" "<<j<<endl;
	if(dp[i][j]){
		ans=max(ans,__builtin_popcount(i));
	}
	
			}
		}
	}
	
	cout<<n-ans<<endl;
}
int main() {
    cin.tie(0);
    
    ios::sync_with_stdio(false);

    int t;
   cin>>t;
     //t=1;
    while (t--) {
solve();
    }
    return 0;
}

最短哈密顿路径

https://www.acwing.com/problem/content/93/

主要就是需要不重不漏的走一遍并且维护最短路,这无法在多项式时间内完成,在n不大的时候我们用二级制枚举所有状态,枚举终点作为状态,转移是通过枚举上一个点。

时间复杂度:O(\(2^n*n^2\))

// Problem: 最短Hamilton路径
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/93/
// Memory Limit: 256 MB
// Time Limit: 5000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
using namespace std;
#define ll long long
//# define int long long
#define ull unsigned long long
#define pii pair<int,int>

#define baoliu(x, y) cout << fixed << setprecision(y) << x
#define endl  "\n"
#define debug1(x) cerr<<x<<" "
#define  debug2(x) cerr<<x<<endl
const int N = 21;
const int M = 1e6 + 10;
const int inf = 0x3f3f3f3f;
const int mod = 998244353;
const double eps = 1e-8;
int n, m;
int w[N][N];
//首先思考为什么这里最短路不能用普通的最短路
//首先它需要把所有点都遍历到,而普通最短路根本不在乎这个
int dp[1<<20][N];
void solve(){
	cin>>n;
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			cin>>w[i][j];
		}
	}
	
	memset(dp,0x3f ,sizeof dp);
	dp[1][0]=0;
	for(int i=0;i<(1<<n);i++){
		for(int j=0;j<n;j++){//枚举当前终点
			if(((i>>j)&1)==0)continue;
			for(int k=0;k<n;k++){//枚举上一次转移点
				if(((i>>k)&1)==0)continue;
				int pre=i-(1<<j);
				if(k==j)continue;
				dp[i][j]=min(dp[i][j],dp[pre][k]+w[k][j]);
			}
		}
	}
	int ed=(1<<n)-1;
	cout<<dp[ed][n-1];
}
int main() {
    cin.tie(0);
    
    ios::sync_with_stdio(false);

    int t;
   //cin>>t;
     t=1;
    while (t--) {
solve();
    }
    return 0;
}

最短哈密顿回路

https://www.luogu.com.cn/problem/P1171

// Problem: P1171 售货员的难题
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P1171
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
using namespace std;
#define ll long long
//# define int long long
#define ull unsigned long long
#define pii pair<int,int>

#define baoliu(x, y) cout << fixed << setprecision(y) << x
#define endl  "\n"
#define debug1(x) cerr<<x<<" "
#define  debug2(x) cerr<<x<<endl
const int N =21 ;
const int M = 1e6 + 10;
const int inf = 0x3f3f3f3f;
const int mod = 998244353;
const double eps = 1e-8;
int n, m;
int a[N];

int w[N][N];
//首先思考为什么这里最短路不能用普通的最短路
//首先它需要把所有点都遍历到,而普通最短路根本不在乎这个
int dp[1<<20][N];
void solve(){
    cin>>n;
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            cin>>w[i][j];
        }
    }

    memset(dp,0x3f ,sizeof dp);
    dp[1][0]=0;
    for(int i=0;i<(1<<n);i++){
        for(int j=0;j<n;j++){//枚举当前终点
            if(((i>>j)&1)==0)continue;
            for(int k=0;k<n;k++){//枚举上一次转移点
                if(((i>>k)&1)==0)continue;
                int pre=i-(1<<j);
                if(k==j)continue;
                dp[i][j]=min(dp[i][j],dp[pre][k]+w[k][j]);
            }
        }
    }
    int ed=(1<<n)-1;
    int ans=inf;
    for(int i=1;i<n;i++){
    	ans=min(ans,dp[ed][i]+w[i][0]);
    }
    cout<<ans<<endl;
}


int main() {
    cin.tie(0);
    
    ios::sync_with_stdio(false);

    int t;
   //cin>>t;
     t=1;
    while (t--) {
solve();
    }
    return 0;
}

标签:哈密顿,int,状压,long,Limit,https,dp,define
From: https://www.cnblogs.com/mathiter/p/18104044

相关文章

  • 牛客竞赛动态规划专题班数位dp例题
    题单A-0的个数这题算是一个思维题。我的做法是就是统计每一位的0有多少个。例如\(4032\)个位的零有\(403\)种十位的零有\(40*10\)种百位的零有\(3*100+33\)种,即千位去\([1,3]\)个位低两位取\([00,99]\),或者千位取\(4\)低两位取\([00,33]\)千位不能取零#include<......
  • 动态规划 选择dp:多重背包+多重背包puls----中专生刷算法
    不了解动态规划和选择dp的同学先看一下这两篇文章动态规划:选择dp及优化01背包问题-CSDN博客动态规划:完全背包问题----中专生刷算法-CSDN博客然后我们来做题普通题+进阶题,图文详解,化零为整的解决多重背包puls问题!!!多重背包输入格式输出格式输出一个整数,表示最......
  • CAN转PROFIBUS DP网关助力和利时PLC连接潍柴发电机组
    潍柴,作为柴油机行业的翘楚,其产品被广泛地应用于通信、石油、医疗、铁路以及农牧业等多个领域。 南通某项目有多台即将发往国外的潍柴发电机组,客户新需发电机组增加PROFIBUSDP接口以达到与上位系统和利时PLC实时通信。 该项目中,上位机系统需实时监控柴油机的转速,机油压力和......
  • 数位dp
    数位dphttps://leetcode.cn/problems/reverse-bits-lcci/description/publicintreverseBits(intnum){intmax=0;intdp1=0;intdp2=0;for(inti=0;i<32;i++){if((num&1)==1){......
  • 02-基于STM32F407MAC与DP83848实现以太网通讯六(IPerf网络速度测试)
    一、IPerf2网络测试工具Iperf2是一个用于测试网络带宽的工具。它是Iperf的旧版本,专注于提供基本的带宽测量功能。通过在客户端和服务器之间发送测试数据流并测量其性能,用户可以评估网络连接的速度和稳定性。Iperf2提供了一种简单而有效的方式来评估网络性能。IPerf3已经发布了,但......
  • 状压 dp
    引入先看一道例题:(可能r18)有\(N\)个男生和\(N\)个女生。小A喜欢磕CP,现在小A想要磕\(N\)对CP。不过每一个人都有自己的npy,也不是随随便便就能磕成一对。现在小A找到了你,要你求出有多少种磕CP的方式。我们显然可以暴力枚举每一个男生跟谁组CP然后判断是否合法......
  • 状压DP
    状压就是把几个维度压成一个维度,通常是按\(k\)进制来压缩如dp[(1<<1145141919810)]这样相当于开了\(1145141919810\)个只有\(0/1\)的维度,二进制下每一位表示这个维度运行逝世查询一个集合\(s\)的所有子集合扩散行for(inti=s;i<MAXN;i=(i+1)|s......
  • 设计模式DP-外观模式
    #include<stdio.h>#include<string.h>#include<stdlib.h>//定义子系统AtypedefstructsubsystemA{ void(*operationA)(structsubsystemA*subsystem);}SubsystemA;//定义子系统BtypedefstructsubsystemB{ void(*operationB)(structsubsystem......
  • 设计模式DP-责任链模式
    #include<stdio.h>#include<string.h>#include<stdlib.h>//定义业务处理者抽象类typedefstructHandler{ structHandler*nextHandler; void(*handleRequest)(structHandler*handler,intrequest); void(*setNextHandler)(structHandler*CurHan......
  • 设计模式DP-表驱动模式
    静态结构体数组式构建链表式构建链接式构建#include<stdio.h>#include<stdlib.h>#include<string.h> //加doublefun_add(doubledata_front,doubledata_back){ returndata_front+data_back;}//减doublefun_sub(doubledata_front,doubledata_back)......