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;
    }
  • 相关阅读:
    移动开发 Native APP、Hybrid APP和Web APP介绍
    urllib与urllib2的学习总结(python2.7.X)
    fiddler及postman讲解
    接口测试基础
    UiAutomator2.0 和1.x 的区别
    adb shell am instrument 命令详解
    GT问题记录
    HDU 2492 Ping pong (树状数组)
    CF 567C Geometric Progression
    CF 545E Paths and Trees
  • 原文地址:https://www.cnblogs.com/wangxiaodai/p/9878420.html
Copyright © 2011-2022 走看看