zoukankan      html  css  js  c++  java
  • 51nod 1326 遥远的旅途

    一个国家有N个城市,这些城市被标为0,1,2,...N-1。这些城市间连有M条道路,每条道路连接两个不同的城市,且道路都是双向的。一个小鹿喜欢在城市间沿着道路自由的穿梭,初始时小鹿在城市0处,它最终的目的地是城市N-1处。小鹿每在一个城市,它会选择一条道路,并沿着这条路一直走到另一个城市,然后再重复上述过程。每条道路会花费小鹿不同的时间走完,在城市中小鹿不花时间逗留。路程中,小鹿可以经过一条路多次也可以经过一个城市多次。给定城市间道路的信息,问小鹿是否有一种走法,从城市0出发到达城市N-1时,恰好一共花费T个单位的时间。如果存在输出“Possible”,否则输出“Impossible”。
    注意,小鹿在整个过程中可以多次经过城市N-1,只要最终小鹿停在城市N-1即可。
     
    例如样例中小鹿的行程可以是0->1->2->0->2.
    Input
    多组测试数据,输入的第一行含一个整数caseT,表示测试数据个数,1<=caseT<=3.
    之后有caseT组相同结构的测试数据,每组测试数据构成如下:
    第一行三个整数,N,M,T,且2<=N<=50,1<=M<=50,1<=T<=1,000,000,000,000,000,000(即
    10^18).
    之后M行,每行三个整数Ai,Bi,Di,表示城市Ai与Bi间有一条双向道路,且小鹿穿越这条路要花费Di的时间。其中,0<=Ai,Bi<N,1<=Di<=10000。
    Output
    每组测试数据一行输出,如果存在题目所述路径输出“Possible”,否则“Impossible”,不含引号。
    Input示例
    1
    3 3 25
    0 2 7
    0 1 6
    1 2 5
    Output示例
    Possible

    题解:
      这个题目暴力dp,一定连空间都开不下,但这个已经是凑数模型的唯一状态,没有什么其他办法,所以,一定要想着题目中的其他限制或者说性质。
      因为这个是一个图论模型,所以转移就十分有限制,只能走边权,所以我们可以发现要凑出这个数,就一定是先到n号点,然后通过走一条边2*k遍来达到目的,所以我们可以列出式子,(t-dis(1~n))%2*k==0(k为和n号点相连的某条边的边权))
    转化成t%(2*k)==dis(1~n)%(2*k)。用这个式子,我们就只要看是否存在一条到n的路径,使得路径的边权和%2*k等于一个定值t%(2*k)。
      因为这个题目和模数有关,所以我们要把取摸的结果写入状态,dp[i][j]表示处于i节点,从一号点到i号点的花费和%(2*k)(选择的边权)等与k的最小花费,那么转移就是dp[to][(j+quan)%mod]=min(dp[now][j]+quan).
      可以说是有限制的凑数问题吧,因为这个题目是一个图,有后效性,所以spfa。

    代码:
    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cmath>
    #include <iostream>
    #include <queue>
    #define MAXN 200
    #define MAXN2 20100
    #define ll long long
    using namespace std;
    ll dis[MAXN][MAXN2];
    bool have[MAXN][MAXN2];
    struct edge{
        int first;
        int next;
        int to;
        int quan;
    }a[MAXN*2];
    struct node{
        int now,ti;
    };
    queue<node> q;
    int n,m,num=0;ll t,mod;
    
    void addedge(int from,int to,int quan){
        a[++num].to=to;
        a[num].quan=quan;
        a[num].next=a[from].first;
        a[from].first=num;
    }
    
    void spfa(){
        memset(dis,127,sizeof(dis));
        memset(have,0,sizeof(have));
        while(!q.empty()) q.pop();
        have[1][0]=1,dis[1][0]=0;
        q.push((node){1,0});
        while(!q.empty()){
            node hh=q.front();q.pop();
            int now=hh.now,t=hh.ti;
            have[now][t]=0;
            for(int i=a[now].first;i;i=a[i].next){
                int to=a[i].to,quan=a[i].quan,tt=(t+quan)%mod;
                if(dis[to][tt]>dis[now][t]+quan){
                    dis[to][tt]=dis[now][t]+quan;
                    if(!have[to][tt]){
                        have[to][tt]=1;
                        q.push((node){to,tt});
                    }
                }
            }
        }
    }
    
    void work(){
        scanf("%d%d%lld",&n,&m,&t);
        memset(a,0,sizeof(a));int flag=0;num=0;
        for(int i=1;i<=m;i++){
            int x,y,z;scanf("%d%d%d",&x,&y,&z);x++,y++;
            addedge(x,y,z),addedge(y,x,z);
        }
        for(int i=a[n].first;i;i=a[i].next){
            int quan=a[i].quan;
            mod=quan*2;
            spfa();
            if(dis[n][t%mod]<=t){
                printf("Possible
    ");flag=1;
                break;
            }
        }
        if(!flag){
            printf("Impossible
    ");
        }
    }
    
    int main()
    {
        int t;cin>>t;
        while(t--){
            work();
        }
        return 0;
    }
  • 相关阅读:
    [leetcode]95 Unique Binary Search Trees II (Medium)
    [leetcode] 96 Unique Binary Search Trees (Medium)
    [leetcode] 72. Edit Distance (hard)
    [leetcode] 120. Triangle (Medium)
    [leetcode] 63. Unique Paths II (medium)
    [OpenGL] 不规则区域的填充算法
    [leetcode] 64. Minimum Path Sum (medium)
    ESLint入坑
    报错:for..in loops iterate over the entire prototype chain, which is virtually never what you want.
    vue解决seo优化之预渲染prerender-spa-plugin
  • 原文地址:https://www.cnblogs.com/renjianshige/p/7588125.html
Copyright © 2011-2022 走看看