ACM-DFS之Jerboas——hdu2437

Jerboas
题目: http://acm.hdu.edu.cn/showproblem.php?pid=2437
Problem Description
Jerboas are small desert-living animals, which resemble mice with a long tufted tail and very long hind legs. Jerboas shelter in well-hidden burrows. They create two types of burrow: temporary and permanent. The temporary burrows are plain tubes while the permanent burrows are sealed with a plug of sand to keep heat out and moisture in.

As far as we know, jerboa burrows in the desert are connected with one-way tunnels. What's more, for some unknown reasons, it's true that start from any burrow, follows the tunnels you can not go back to the starting burrow.
Summer means last-minute of offers on good times, so of course jerboas could not stay behind. One day, a little jerboa Alice who lived in a temporary burrow S wants to migrate to a permanent one. There are different routes she can take, but Alice is so odd that she only selects those whose total travel distances is a multiple of K. Among all routes that Alice may select, we are interested in the shortest one. Can you help to find it out? Of course different routes may lead to different destinations.

Input
On the first line of input, there is a single positive integer T <= 20 specifying the number of test cases to follow.
Each test case starts with four integers in the first line: N, M, S, K.
N is the number of burrows in the desert (burrows are numbered with 1, 2, …, N);
M is the number of tunnels connecting the burrows;
S is where Alice lived and K is as described above.
(0 < N <= 1000, 0 <= M <= 20000, 0 < S <= N, 0 < K <= 1000)
The second line contains N characters each could be ‘T’ or ‘P’. The i-th character specifying the type of the burrow i. ‘T’ means temporary burrow, ‘P’ means permanent burrow. It’s guaranteed that the S-th character is ‘T’.
Next follow M lines, each line with 3 integers A, B, C. Specifying that there is a tunnel from burrow A to burrow B, and its length is C.
(0 < A, B <= N, A != B, 0 < C < 40000)

Output
For each test case you should output a single line containing "Case X: Y Z" (quotes for clarity) where X is the number of the test case (starting at 1) and Y is the length of the shortest route Alice can select and Z is the destination of the selected route.
Notice that burrow Z should be a permanent burrow.
In case there’s more than one solution, Z should be the minimum.
In case there's no solution, Y and Z should be both equal to -1.

Sample Input
2
5 5 1 7
TPPTP
1 2 8
1 4 7
4 3 9
2 3 6
1 5 3
5 5 1 7
TPTTP
1 2 8
1 4 7
4 3 9
2 3 6
1 5 3

Sample Output
Case 1: 14 3

Case 2: -1 -1


题意:沙漠中有个小老鼠(姑且认为是老鼠吧),它要找一个窝来在沙漠生存,有一些时临时的窝T,也有永久的窝P,现在它从一个临时的窝出发,去找永久的窝,问:最近的那个窝在哪,距离有多远。

限制:这个老鼠,一次只能走K步,换句话说就是从起点到终点的距离必须是K的倍数。

依旧是DFS题目,当时理解题意,直接做出来,TLE。。。

好吧,后来以为是建立二维数组存储从i点到达j点距离有点太大,于是用结构体存储,提交。。。TLE

终于发现,这道题目是考剪枝额,能剪的地方看只有vis数组上下手了。。

做这么多DFS也做过,vis数组改动的无外乎距离么,这道题也往那方面想,很快就能想出来:

假设从1号点出发,到达2号点有三条路,第一条路长度为4,第二条路长度为11。

假设K为7:那么第一条路和第二条路只需要搜索一次,不需要重复搜索。

为什么呢?因为4%7=4  11%7=4 ,还不懂?

因为最后从起点到终点的距离要是7的倍数,其实加的就是对7的求模,什么时候等于0,并且当时的点为P,就OK


然后当距离相等时,不要忘了,点也要取最近的(因为这个WA一次)


#include <iostream>
#include <string.h>
using namespace std;
char coor[1001];
bool vis[1001][1001];
int N,M,k,finish,minn;
bool ispos;

struct Map
{
    int len;
    int to[1001][2];
}m[1001];

void dfs(int x,int sum)
{
    if(sum>minn)    return;
    if(sum%k==0 && coor[x]=='P' && sum!=0)
    {
        ispos=1;
        // 不光距离要取最小,当距离相同时点也要取最近的
        if(minn>=sum)
        {
            minn=sum;
            if(finish>x)
                finish=x;
        }
        return;
    }
    int i,total;
    for(i=0; i<m[x].len; ++i)
    {
        total=sum+m[x].to[i][1];
        // 对于vis数组的一个剪枝
        if(vis[m[x].to[i][0]][total%k]>total || !vis[m[x].to[i][0]][total%k])
        {
            vis[m[x].to[i][0]][total%k]=total;
            dfs(m[x].to[i][0],total);
        }

    }
}

int main()
{
    int s,i,num,a,b,c,t;
    cin>>t;
    for(num=1;num<=t;++num)
    {
        cin>>N>>M>>s>>k;
        memset(m,0,sizeof(m));
        memset(vis,0,sizeof(vis));

        for(i=1;i<=N;++i)   cin>>coor[i];
        for(i=0;i<M;++i)
        {
            cin>>a>>b>>c;
            m[a].to[m[a].len][0]=b;
            m[a].to[m[a].len][1]=c;
            ++m[a].len;
        }
        ispos=0;
        finish=1002;
        minn=999999;
        dfs(s,0);

        if(!ispos)  cout<<"Case "<<num<<": -1 -1"<<endl;
        else    cout<<"Case "<<num<<": "<<minn<<" "<<finish<<endl;
    }
    return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ACM-ICPC(国际大学生程序设计竞赛)是一项面向大学生的计算机编程竞赛,涉及算法和数据结构等领域。在比赛中,选手需要解决一系列编程问题,使用合适的算法和数据结构来实现正确和高效的解决方案。 对于整理ACM-ICPC模板,以下是一些建议: 1. 了解比赛要求:首先,你需要了解ACM-ICPC比赛的具体要求和规则。这包括了解比赛所涉及的算法和数据结构,以及题目的类型和难度等。 2. 收集资料:收集与ACM-ICPC相关的资料,包括经典算法和数据结构的实现代码、常见问题的解题思路等。可以参考教材、博客、论文等资源。 3. 整理模板:将收集到的资料整理成模板。可以按照算法和数据结构的分类进行整理,例如排序算法、图算法、字符串算法等。对每个模板,添加必要的注释和示例代码,以便理解和使用。 4. 测试代码:对每个模板编写测试代码,确保它们的正确性和可靠性。可以使用已知的测试用例或自行设计测试用例。 5. 更新与扩充:定期更新和扩充模板,以适应ACM-ICPC比赛中新出现的算法和数据结构。同时,根据自己的经验和理解,对模板进行优化和改进。 6. 练习和复习:在比赛之前,利用整理好的模板进行练习和复习。尝试解决一些经典问题,使用模板中的算法和数据结构进行实现,并进行优化。 希望这些建议对你整理ACM-ICPC模板有所帮助!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值