zoukankan      html  css  js  c++  java
  • 搜索+剪枝——运筹帷幄 (road.cpp)

    运筹帷幄

    (road.cpp)

    【题目描述】

           刘邦军行至迷糊林,见其中瘴气围绕,又有青狼猛虎之兽,难于前行。

           已知迷糊林是一个共有n个结点的图,点与点之间共有m条道路相连接,每条路有参数t,c,分别表示行走于该路的时间以及兵士损失量。你已知道,刘邦除了脸皮厚什么都不会而且兵力少得可怜,所以需要在还能有兵士存活的情况下尽快走出迷糊林。

           刘邦踞鞍而问曰:“子房,如之奈何?”。

    【文件格式】
    输入文件:

           第一行两个整数n,m,表示节点数以及边数。

           以下m行每行4个整数u,v,c,t,表示u点以及v点之间有一条参数为c,t的边,c为兵士损失量,t为耗费时间。

           第m+2行有两个整数s,t,表示起点与终点。

           第m+3行有一个整数k,表示刘邦军的兵力。

    输出文件:

           一个整数表示能走出迷糊林的最短时间,如果不能走出请输出-1。

    【样例数据】

    Input(road.in)
    4 5
    1 2 2 3
    1 3 3 5
    1 4 7 10
    2 4 4 6
    3 4 2 6
    1 4
    5

    Output (road.out)

    11

    【数据约定】

           n<=5000 ,m<=40000 , c,d<=300 , k<=10^9

    [Hint]

    本题数据随机生成。

    【题目思路】

    这个题主要是搜索,bfs,不过要是只用单纯的搜索的话绝对会超时,超的不止一点。。。。。所以我用了两种剪枝,第一是先spfa一遍图,算出每个点到终点的最短距离,如果当前搜到的点+这个点到终点的最短距离(士兵数)<拥有的士兵总量,直接过;第二是如果时间超过了当前存储的最小时间(迷糊林路的长度),直接过。

    下面上代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring> 
    #include<vector>
    #include<queue>
    
    using namespace std;
    
    const int N = 40000+10;
    
    struct Edge { int v,b,t,next;
    }e[N*2];
    int en=0,front[N];
    
    int m,n,u,v,b,t; 
    int qi,zhong;
    int liu;
    int d[40001];
    
    void adde(int u,int v,int b,int t) {
    	en++; e[en].v=v , e[en].b=b , e[en].t=t , e[en].next=front[u]; 
    	front[u]=en;
    }
    
    void spfa() {
    	queue<int> q;
    	bool inq[40001];
    	memset(inq,0,sizeof(inq));
    	for(int i=1;i<=m;i++) d[i]=1e9+1e9;
    	d[zhong]=0;inq[zhong]=1; q.push(zhong);
    	while(!q.empty())
    	{
    		int u=q.front(); q.pop(); inq[u]=false;
    		for(int i=front[u];i;i=e[i].next) {
    			Edge es=e[i];
    			int v=es.v;
    			if(d[v]>d[u]+es.b) {
    				d[v]=d[u]+es.b;
    				if(!inq[v])
    					q.push(v) , inq[v]=1;
    			}
    		}
    	}
    }
    
    bool dg[5001];
    int bd=0,bt=0; 
    int small=1e9;
    
    void dfs(int u,int blood,int dist)
    {
    	if(u==zhong) { small=dist; return; }
     	for(int i=front[u];i;i=e[i].next) {
    		Edge es=e[i];
    		if(!dg[es.v] && blood-es.b > d[es.v] && dist + es.t < small) {
    			dg[es.v]=1;
    			dfs(es.v,blood-es.b,dist+es.t);
    			dg[es.v]=0;
    		}
    	}
    }
    void read(int& x) {
    	char c=getchar(); 
    	while(!isdigit(c)) c=getchar();
    	x=0;
    	while(isdigit(c)) {
    		x=x*10+c-'0';
    		c=getchar();
    	}
    }
    int main()
    {
    	freopen("road.in","r",stdin);
    	freopen("road.out","w",stdout);
    	read(m),read(n);
    	 //memset(dg,0,sizeof(dg));
    	 for(int i=1;i<=n;i++)
    	 { 
    	 	read(u),read(v),read(b),read(t);
    	 	adde(u,v,b,t); adde(v,u,b,t);
    	 }
    	 read(qi),read(zhong),read(liu);
    	 spfa();
    	 if(d[qi] > liu)
    	 {
    	 	cout<<"-1";
    	 }
    	 else
    	 {
    	 	dg[qi]=1;
    	 	dfs(qi,liu,0);
    	 	cout<<small;
    	 }
    	 return 0;
    }
    

      数据:http://files.cnblogs.com/files/zhangone/road.zip

    (以上代码数据中十个点全过)

    感谢李学长在我各种蒟蒻的时候耐心讲解。

  • 相关阅读:
    IEEE 网址
    知乎上非常棒的机器学习专栏
    怎样认识比你优秀的人并和他们成为朋友?
    影藏铜皮,显示原点与更改
    PCB检查事项,生成钻孔表
    布局-同样模块复用
    制作DIP Package及DIP焊盘制作,不规则焊盘制作
    制作SMD Package及SMD焊盘制作
    导入网络表
    导入DXF文件
  • 原文地址:https://www.cnblogs.com/zhangone/p/5131717.html
Copyright © 2011-2022 走看看