zoukankan      html  css  js  c++  java
  • ACM: 强化训练-海贼王之伟大航路-dfs-枝减

    海贼王之伟大航路
    Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u

    Description

    “我是要成为海贼王的男人!”,路飞一边喊着这样的口号,一边和他的伙伴们一起踏上了伟大航路的艰险历程。

    路飞他们伟大航路行程的起点是罗格镇,终点是拉夫德鲁(那里藏匿着“唯一的大秘宝”——ONE PIECE)。而航程中间,则是各式各样的岛屿。

    因为伟大航路上的气候十分异常,所以来往任意两个岛屿之间的时间差别很大,从A岛到B岛可能需要1天,而从B岛到A岛则可能需要1年。当然,任意两个岛之间的航行时间虽然差别很大,但都是已知的。

    现在假设路飞一行从罗格镇(起点)出发,遍历伟大航路中间所有的岛屿(但是已经经过的岛屿不能再次经过),最后到达拉夫德鲁(终点)。假设他们在岛上不作任何的停留,请问,他们最少需要花费多少时间才能到达终点?

    Input

    输入数据包含多行。 
    第一行包含一个整数N(2 < N ≤ 16),代表伟大航路上一共有N个岛屿(包含起点的罗格镇和终点的拉夫德鲁)。其中,起点的编号为1,终点的编号为N。 
    之后的N行每一行包含N个整数,其中,第i(1 ≤ i ≤ N)行的第j(1 ≤ j ≤ N)个整数代表从第i个岛屿出发到第j个岛屿需要的时间t(0 < t < 10000)。第i行第i个整数为0。

    Output

    输出为一个整数,代表路飞一行从起点遍历所有中间岛屿(不重复)之后到达终点所需要的最少的时间。

    Sample Input

    样例输入1:
    4
    0 10 20 999
    5 0 90 30
    99 50 0 10
    999 1 2 0
    
    样例输入2:
    5
    0 18 13 98 8
    89 0 45 78 43 
    22 38 0 96 12
    68 19 29 0 52
    95 83 21 24 0

    Sample Output

    样例输出1:
    100
    
    样例输出2:
    137

    Hint

    提示: 
    对于样例输入1:路飞选择从起点岛屿1出发,依次经过岛屿3,岛屿2,最后到达终点岛屿4。花费时间为20+50+30=100。 
    对于样例输入2:可能的路径及总时间为: 
    1,2,3,4,5: 18+45+96+52=211 
    1,2,4,3,5: 18+78+29+12=137 
    1,3,2,4,5: 13+38+78+52=181 
    1,3,4,2,5: 13+96+19+43=171 
    1,4,2,3,5: 98+19+45+12=174 
    1,4,3,2,5: 98+29+38+43=208 
    所以最短的时间花费为137 
    单纯的枚举在N=16时需要14!次运算,一定会超时。
     
    /*/ 
    中文题。。。。 
    题目告诉我们直接历遍会超时,所以需要去剪枝,关键是怎么剪枝。
    这里有几个思路:
    1.减去途中已经比之前的mint更大的枝;
    2.从1经过2 3 4 到达 5有很多种方法,记录到达这个时候的最小时间,减去比到达这个状态耗时更多的状态。 
    
    /*/ 
    
    #include"iostream"
    #include"cstdio"
    #include"cstring"
    #include"algorithm"
    using namespace std;
    
    //神奇的二进制强行搜索。。。 
    int vis[17][1<<18];
    //一开始 vis 我设置的是一维的发现虽然已经走过的岛虽然已经成功记录,但是现在所在的岛可能不同,所以还得加一维。
    int node[17][17];
    bool ifgone[17];
    //记录岛是否走过
    int mint;
    int x,T;
    void dfs(int nowland,int nowtime,int nowstate) {
    	x++;		//这里是走过的岛的个数
    	ifgone[nowland]=1;
    	if(x==T-1) {//如果走到了倒数第二个岛,直接加上该岛到最后一个岛的时间比较最小时间,深搜结束
    		mint=min(mint,nowtime+node[nowland][T]);
    		return;
    	}
    	if(nowtime>=mint) {//如果已经超过最小的时间了,深搜结束;
    		return;
    	}
    	if(nowtime<vis[nowland][nowstate]||vis[nowland][nowstate]==0) {
    		vis[nowland][nowstate]=nowtime;
    	} else return;  //如果现在这个状态和之前来过的相同状态比所用时间要更加大的话,深搜结束;
    
    	for(int i=1; i<T; i++) {
    		if(ifgone[i]==0) { //继续往没走过的岛去搜索
    			dfs(i,nowtime+node[nowland][i],nowstate+((1<<nowland-1)));  //【1<<nowland  和 noland<<1 这两个一个是2^nowland 一个是nowland*2  找了好久。。。】 
    			x--;
    			ifgone[i]=0;//这里要记得清空走过的标记
    		}
    	}
    
    }
    
    int main() {
    	while(~scanf("%d",&T)) {
    		for(int i=1; i<=T; i++) {
    			for(int j=1; j<=T; j++) {
    				scanf("%d",&node[i][j]);
    			}
    		}
    		x=0;
    		memset(vis,0,sizeof(vis));
    		memset(ifgone,0,sizeof(ifgone));
    		mint=1<<29;
    		dfs(1,0,1);
    		printf("%d
    ",mint);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    2017ccpc全国邀请赛(湖南湘潭) E. Partial Sum
    Codeforces Round #412 C. Success Rate (rated, Div. 2, base on VK Cup 2017 Round 3)
    2017 中国大学生程序设计竞赛 女生专场 Building Shops (hdu6024)
    51nod 1084 矩阵取数问题 V2
    Power收集
    红色的幻想乡
    Koishi Loves Segments
    Wood Processing
    整数对
    Room and Moor
  • 原文地址:https://www.cnblogs.com/HDMaxfun/p/5713128.html
Copyright © 2011-2022 走看看