zoukankan      html  css  js  c++  java
  • 最短路+状压DP【洛谷P3489】 [POI2009]WIE-Hexer

    P3489 [POI2009]WIE-Hexer

    大陆上有n个村庄,m条双向道路,p种怪物,k个铁匠,每个铁匠会居住在一个村庄里,你到了那个村庄后可以让他给你打造剑,每个铁匠打造的剑都可以对付一些特定种类的怪物,每条道路上都可能出现一些特定种类的怪物,每条道路都有一个通过所需要的时间,现在要从1走到n,初始的时候你没有剑,要求在经过一条道路的时候,对于任意一种可能出现在这条道路上的的怪物,你都有已经有至少一把剑可以对付他,求从1走到n的最短时间(打造剑不需要时间)

    最短路上状压DP。

    可以把当前对于可不可以消灭每种怪物压成一个状态,跟随最短路转移即可。

    code:

    #include <iostream>
    #include <cstdio>
    #include <queue>
    
    #define int long long
    
    using namespace std;
    
    const int wx=20017;
    
    inline int read(){
    	int sum=0,f=1; char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
    	while(ch>='0'&&ch<='9'){sum=(sum<<1)+(sum<<3)+ch-'0'; ch=getchar();}
    	return sum*f;
    }
    
    int head[wx],dis[217][wx],vis[217][wx];
    int flag[wx];
    int num,n,m,p,WX,ans=0x3f3f3f3f,k;
    
    struct e{
    	int nxt,to,dis,flag;
    }edge[wx*2];
    
    void add(int from,int to,int dis,int flag){
    	edge[++num].nxt=head[from];
    	edge[num].to=to;
    	edge[num].dis=dis;
    	edge[num].flag=flag;
    	head[from]=num;
    }
    
    struct node{
    	int u,d,flag;
    	friend bool operator < (const node & a,const node & b){
    		return a.d>b.d;
    	}
    };
    
    priority_queue<node > q;
    
    void Dij(){
    	for(int i=1;i<=n;i++)
    		for(int j=0;j<WX;j++)
    			dis[i][j]=0x3f3f3f3f,vis[i][j]=0;
    	q.push((node){1,0,flag[1]}); dis[1][flag[1]]=0;
    	while(q.size()){
    		int u=q.top().u; int flaag=q.top().flag; q.pop();
    		if(vis[u][flaag])continue; vis[u][flaag]=1;
    		for(int i=head[u];i;i=edge[i].nxt){
    			int v=edge[i].to;
    			if((flaag&edge[i].flag)!=edge[i].flag)continue;
    			if(dis[v][flaag|flag[v]]>dis[u][flaag]+edge[i].dis){
    				dis[v][flaag|flag[v]]=dis[u][flaag]+edge[i].dis;
    				q.push((node){v,dis[v][flaag|flag[v]],flaag|flag[v]});
    				if(v==n)ans=min(ans,dis[v][flaag|flag[v]]);
    			}
    		}
    	}
    	for(int i=0;i<WX;i++)ans=min(ans,dis[n][i]);
    }
    
    signed main(){
    	n=read(); m=read(); p=read(); k=read();
    	WX=(1<<p+1);
    	for(int i=1;i<=k;i++){
    		int x,y;x=read(); y=read();
    		for(int j=1;j<=y;j++){
    			int z; z=read();
    			flag[x]|=(1<<z);
    		}
    	}
    	for(int i=1;i<=m;i++){
    		int x,y,z,c,zmj=0;
    		x=read(); y=read(); z=read(); 
    		c=read();
    		for(int j=1;j<=c;j++){
    			int b; b=read(); zmj|=(1<<b);
    		}
    		add(x,y,z,zmj); add(y,x,z,zmj);
    	}
    	Dij();
    	if(ans==0x3f3f3f3f)ans=-1;
    	printf("%lld
    ",ans);
    	return 0;
    }
  • 相关阅读:
    C++ 单例模式
    单链表快速排序
    美团后台面经
    排序算法及其优化总结
    (转)再谈互斥量与环境变量
    互斥锁和自旋锁
    算法题总结----数组(二分查找)
    Linux里的2>&1的理解
    Ubuntu下开启mysql远程访问
    说说eclipse调优,缩短启动时间
  • 原文地址:https://www.cnblogs.com/wangxiaodai/p/9878420.html
Copyright © 2011-2022 走看看