dfs好题一道

There are n Doge Planets in the Doge Space. The conqueror of Doge Space is Super Doge, who is going to inspect his Doge Army on all Doge Planets. The inspection starts from Doge Planet 1 where DOS (Doge Olympic Statue) was built. It takes Super Doge exactly T xy time to travel from Doge Planet x to Doge Planet y.

With the ambition of conquering other spaces, he would like to visit all Doge Planets as soon as possible. More specifically, he would like to visit the Doge Planet x at the time no later than Deadline x. He also wants the sum of all arrival time of each Doge Planet to be as small as possible. You can assume it takes so little time to inspect his Doge Army that we can ignore it. 

There are multiple test cases. Please process till EOF.
Each test case contains several lines. The first line of each test case contains one integer: n, as mentioned above, the number of Doge Planets. Then follow n lines, each contains n integers, where the y-th integer in the x-th line is T xy . Then follows a single line containing n - 1 integers: Deadline 2 to Deadline n.
All numbers are guaranteed to be non-negative integers smaller than or equal to one million. n is guaranteed to be no less than 3 and no more than 30.

If some Deadlines can not be fulfilled, please output “-1” (which means the Super Doge will say “WOW! So Slow! Such delay! Much Anger! . . . ” , but you do not need to output it), else output the minimum sum of all arrival time to each Doge Planet.

Sample Input

4
0 3 8 6
4 0 7 4
7 5 0 2
6 9 3 0
30 8 30
4
0 2 3 3
2 0 3 3
2 3 0 3
2 3 3 0
2 3 3
Sample Output

36
-1
题目的大意是说给个n乘n的矩阵D,Dxy表示从x到y的距离,然后从0开始移动,每个点都要经过,而且到达每个点的时间必须在限制范围内,且每个点可以重复到达,求走完所有点所需最短时间,如果在条件范围内无法走完所有点,就输出-1。

一开始拿到题目,想到的是bfs,当然,最小路径嘛,不过仔细想想就觉得不对,于是又多想了几遍,今天整个下午都在想这题,结果都没想出来,不过有段时间还是给我找到了头绪,就是先求出从一个点到另一个点的最小距离,(因为一开始给的并不是最小距离,有可能折返过后比直接到达还短)只是当时还缺点东西,于是依旧不能解决问题,即使后来用了一个十分暴力的方法也是TLE。

后来实在想不出解法时,我查到了求到每个点的最小距离的解法,而且很简单,如下:

for(int k=0;k<n;k++)
	for(int i=0;i<n;i++)
               	 for(int j=0;j<n;j++)
                   	 s[i][j]=min(s[i][j],s[i][k]+s[k][j]);
如果存在比直达还要短的路径,那么肯定存在一个只折一次到某点比直接到达该点的距离短,于是只要遍历就可以找到最短路径。

或者另一种理解思路:先选定一个点,再找另一个点,可以遍搜从这个点到另一个点再折到选定的点的所有情况,找到最小,再更换选定的点,再搜,可以遍历所有情况。

接下来就是直接的dfs了。

代码如下:

#include <stdio.h>
#include <iostream>
#include <cstring>
#include <stdlib.h>
#include <algorithm>
#include <queue>
#include <math.h>
#define MAX 35
#define INF 1e8

using namespace std;
int n;//n个数
int line[MAX];//到每个点的时间限制
int s[MAX][MAX];//输入的矩阵
int digi[MAX];//标记每个点是否走过,因为在找出最短路径之后,就等于没有了点可以重复走的条件了
int ans;//答案
void dfs(int a,int tim,int t)//现在的点a,现在的时间tim,前面到达各个点时间和t
{
    int count1=0;
    for (int i = 1;i < n;i++)
    {
        if(digi[i]==0)
            count1++;
        if(digi[i]==0&&tim>line[i])
            return;
    }//剪枝
    if(count1&&t+tim*count1>ans)
        return;
    else if(!count1)
    {
        ans=min(t,ans);
    }
    for (int i=1;i<n;i++)
    {
        if(i!=a&&digi[i]==0&&tim+s[a][i]<=line[i])
        {
            digi[i]=1;
            dfs(i,tim+s[a][i],t+tim+s[a][i]);
            digi[i]=0;
        }
    }
}
int main(void)
{
    while (scanf("%d",&n)!=EOF)
    {
        for (int i = 0;i < n;i++)
        {
            for (int j = 0;j < n;j++)
            {
                scanf("%d",&s[i][j]);
            }
        }
        for(int k=0;k<n;k++)
            for(int i=0;i<n;i++)
                for(int j=0;j<n;j++)
                    s[i][j]=min(s[i][j],s[i][k]+s[k][j]);//找出一个点到各个点的最小值
        for (int i = 1;i < n;i++)
            scanf("%d",&line[i]);
        ans=INF;
        dfs(0,0,0);
        if(ans==INF)
            cout<<-1<<endl;
        else
            cout<<ans<<endl;
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值