HDU 4848 Wow! Such Conquering! (DFS)

本文深入探讨了一项独特的星际旅行任务,目标是在一系列即将毁灭的星球消失前逐一造访,通过巧妙运用DFS算法并辅以剪枝策略,计算完成这一壮举所需的最短时间。文章详细阐述了算法实现过程,包括状态转移矩阵的构建、死期限制的考虑以及优化路径选择的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:有n个星球,我从第0个星球出发,后n-1个星球都有死期,我要争取在他们毁灭之前将他们都拜访一次,如果我能成功,输出我到达每个星球的时间的和(不是拜访完的最短用时),不能成功则输出-1。


思路:用dfs然后剪枝。


#include 
#include 

int n, dist[40][40], vis[40], deadline[40], summin;

void dfs(int v, int left ,int prevtime, int sum)
{
    int i;
    if(left == 0)
    {//所有星球都拜访过了,summin有可能改变,将当前到各个星球的用时之和sum与之前确定的用时之和summin比较
        if(sum < summin) summin = sum;
        return ;
    }
    for(i = 1; i < n; i++)
    {//如果在当前已用时间prevtime的情况下无法在某星球毁灭前到达该星球,summin值不会改变,剪枝
        if(vis[i] != 1 && prevtime + dist[v][i] > deadline[i])
        {
                return ;
        }
    }
    for(i  = 1; i < n; i++)
        if( vis[i] != 1 &&(sum + dist[v][i]) < summin)
        {//当前到各个星球的用时之和sum小于summin,summin才可能改变,需要继续搜索
            vis[i] = 1;
            dfs(i, left - 1, prevtime + dist[v][i], sum + left * dist[v][i]);
            vis[i] = 0;
        }
}

void floyd()
{
    int k, i, j;
    for(k = 0; k < n; k++)
        for(i = 0; i < n; i++)
            for(j = 0; j < n; j++)
            {
                if(dist[i][j] > dist[i][k] + dist[k][j])
                //如果考虑经过k点后,从i经过k到j的距离 比 从i只能经过前面k-1个点到j距离短,更新从i到j的最短距离
                    dist[i][j] = dist[i][k] + dist[k][j];
            }
}

int main()
{
    #ifdef LOCAL
    freopen("data.in", "r" ,stdin);
    #endif
    int time, i, j;
    while(scanf("%d", &n) != EOF)
    {
        summin = 1000000;
        memset(vis, 0, sizeof(vis));
        for(i = 0; i < n; i++)
            for(j = 0; j < n; j++)
                scanf("%d", &dist[i][j]);
        for(i = 1; i < n; i++)
            scanf("%d", &deadline[i]);
        floyd();//求两点间的最短路径长度
        vis[0] = 1;
        dfs (0, n - 1, 0, 0);
        if(summin < 1000000)printf("%d\n", summin);
        else printf("-1\n");
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值