关于使用优先队列进行状压DP
查看原帖
关于使用优先队列进行状压DP
374185
Leo_Anderson楼主2024/6/17 21:27

最近自己研究状压DP的时候写出了一种令人眼前一黑的用优先队列进行状压的方法

时间复杂度似乎是 O(n22n+log(n⋅2n))O(n^22^n+log(n·2^n))
(状压DP n22nn^22n ,优先队列 n⋅2nn·2^n 个状态的push和pop为 log(n⋅2n)log(n·2^n) )
(如果算错了请大佬纠正)

这个时间复杂度能通过的题目的数据范围大概在多少(?
(正常状压DP能通过的数据范围是 N≤21N≤21 )


R162453084 记录详情


#include <bits/stdc++.h>
using namespace std;
#define MAXN 16

void DP_init(void);
void Qpush(int now,int hav,int end);

double pm[MAXN][2];
double len[MAXN][MAXN];
double DP[(1<<MAXN)+2][MAXN];
bool vis[(1<<MAXN)+2][MAXN];
int N;

struct my{
	int num,hav,end;
	
	bool operator< (const my x)const{
		if(hav==x.hav){
			if(num==x.num) return end<x.end;
			return num<x.num;
		}
		return hav<x.hav;
	}
	bool operator> (const my x)const{
		if(hav==x.hav){
			if(num==x.num) return end>x.end;
			return num>x.num;
		}
		return hav>x.hav;
	}
	bool operator== (const my x)const{
		if(hav!=x.hav 
		|| num!=x.num 
		|| end!=x.end)return false;
		return true;
	}
};
priority_queue < my , vector<my> , greater<my> > Q;

signed main() {
	cin>>N;
	for(int i=1;i<=N;i++)
		cin>>pm[i][0]>>pm[i][1];
	DP_init();
	//---------------------------
	Qpush(0,0,0);

	while(!Q.empty()){
		my now_get=Q.top();
		while(Q.top()==now_get && !Q.empty()) Q.pop();
		
		int now=now_get.num , nhav=now_get.hav , fp=now_get.end;
		int plus=1,mov=N;
		
		while(mov>0){
			
			if( (now|plus) != now){
				
				if( !vis[(now|plus)][mov] ) {vis[(now|plus)][mov]=true;Qpush((now|plus),nhav+1,mov);}
				
				DP[(now|plus)][mov]=min( DP[(now|plus)][mov] ,DP[now][fp]+len[fp][mov]);
			}
			
			mov--;plus=(plus<<1);
		}
	}
	
	double ans=DP[(1<<N)-1][1];
	for(int i=2;i<=N;i++)	
		ans=min(ans,DP[(1<<N)-1][i]);
		
//	for(int i=1;i<=N;i++)
//		printf("%2d:%.2lf\n",i,DP[(1<<N)-1][i]);
//	cout<<"\n";
		
	printf("%.2lf\n",ans);
	
    return 0;
}

void DP_init(){
	for(int i=0;i<=N;i++){
		for(int j=0;j<=N;j++){
			len[i][j]=sqrt( (pm[i][0]-pm[j][0])*(pm[i][0]-pm[j][0]) + (pm[i][1]-pm[j][1])*(pm[i][1]-pm[j][1]) );
//printf("%.4lf ",len[i][j]);
		}
//cout<<"\n";	
	}
		
			
	for(int i=0;i<(1<<MAXN)+2;i++)
		for(int j=0;j<MAXN;j++)
			DP[i][j]=114514;
			
	DP[0][0]=0;
}

void Qpush(int now,int hav,int end){
	my psin;
    psin.num=now;
	psin.hav=hav;
	psin.end=end;
	Q.push(psin);
}

2024/6/17 21:27
加载中...