状压DP

旅行社问题就是给一个有向图,从点0走一圈全部结点再走回来所花费的费用最少是多少。

状压DP一般n<=15。

因为是走完全部点,那么走到2点的费用有可能走了5,也可能没走,那么就不能简单的用最短路来找。

因为要求跑完全部点回到0,而最小树形图的话无法做到。

状压dp是指在一个点上存在多种状态,这些状态可以用二进制来进行表示。

因为是最后走到0的费用,那么可以有这么个公式dp[S][I]=min(dp[S][i],dp[S|1<

S表示走过的点集合(注意从0开始走,但0这个点没有走过(二进制中其是末尾的1),所以最后走回0)

也就是走完这个集合且目前在v的最小费用,是走完

for(j=0;j

dp[S][I]=min(dp[S][i],dp[S|1<

相当于是从某个顶点退回来的最小费用,也就是这个dp是从终点逆着dp的。

那么只要初始化dp[1<

第一次循环就可以得到走完各个点差一步到0的最小费用,然后再向后dp,直到DP[0][0]

相当dfs的做法:

#include 
#include
#include
#include 
#include 
#include 
#include  
using namespace std;
struct ttt{
	double x1,y1,x2,y2;
};
int dp[1<<17][16];
int map1[16][16];
int n;
int dfs(int S,int v){
	if(dp[S][v]>=0)
	return dp[S][v];
	if(S==(1<>i&1)){
			res=min(res,dfs(S|1<> n >> m;
    for(i=0;i<=n;i++)
    	for(j=0;j<=n;j++)
    		map1[i][j]=1e9+7;//对图的边记得初始化为无穷和判重 
	for(i=1;i<=m;i++){
		cin >> t1>> t2>> t3;
		map1[t1][t2]=t3;
	}
	cout << dfs(0,0) << endl;
  	return 0;
}

初始的时候,需要设置所有初始dp都是无穷大的


#include 
#include
#include
#include 
#include 
#include 
#include  
using namespace std;
struct ttt{
	double x1,y1,x2,y2;
};
int dp[1<<17][16];
int map1[16][16];
int n;
int main(){
	freopen("in.txt","r",stdin);
	//freopen("output.txt","w",stdout);
    int i,j,k,l,f1,f3,t1,t2,t3,m;
    int l1,l2,l3,f4,f5;
    int sum1;
    memset(dp,-1,sizeof(dp));  //之所以可以为-1是因为走到终点后把费用变成0 
    cin >> n >> m;
    for(i=0;i<=n;i++)
    	for(j=0;j<=n;j++)
    		map1[i][j]=1e9+7;//对图的边记得初始化为无穷和判重 
	for(i=1;i<=m;i++){
		cin >> t1>> t2>> t3;
		map1[t1][t2]=t3;
	}
	int S;
	for(S=(1<=0;S--)
		for(i=0;i=0;S--)
		for(i=0;i>j&1)==0) //S中无j 
			dp[S][i]=min(dp[S][i],dp[S|1<



你可能感兴趣的:(----状压DP)