zoukankan      html  css  js  c++  java
  • BZOJ 3890 [Usaco2015 Jan]Meeting Time:拓扑图dp

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3890

    题意:

      给你一个有向图,n个点(n <= 100),m条边。

      且所有的边都是从编号小的点指向编号大的点。

      对于每条边i,Bessie要用c[i]的时间,Elsie要用d[i]的时间(c,d <= 100)。

      Bessie和Elsie从1号点出发,向n号点走去,且两人都不会在路上停留。

      问你使两人同时到达n点的最小时间。若不可能同时到达,输出"IMPOSSIBLE"。

    题解:

      表示状态:

        bool f[i][j] and g[i][j]

        分别表示Bessie和Elsie是否能够同时到达i号点,且花费时间为j。

      找出答案:

        min i with f[n][i] and g[n][i]

        即两人同时到达n的最短时间

      如何转移:

        对于每个点i,一定是从某些编号比i小的点转移而来。

        所以从小到大枚举点i,然后枚举到达时间j,再枚举i能够到达的下一个点dst。

        顺推:

          f[dst][j+c] |= f[i][j]

          g[dst][j+d] |= g[i][j]

      边界条件:

        f[1][0] = g[1][0] = true

    AC Code:

     1 #include <iostream>
     2 #include <stdio.h>
     3 #include <string.h>
     4 #include <vector>
     5 #define MAX_N 105
     6 #define MAX_T 10005
     7 
     8 using namespace std;
     9 
    10 struct Edge
    11 {
    12     int dest;
    13     int c;
    14     int d;
    15     Edge(int _dest,int _c,int _d)
    16     {
    17         dest=_dest;
    18         c=_c;
    19         d=_d;
    20     }
    21     Edge(){}
    22 };
    23 
    24 int n,m;
    25 int ans=-1;
    26 int f[MAX_N][MAX_T];
    27 int g[MAX_N][MAX_T];
    28 vector<Edge> edge[MAX_N];
    29 
    30 void read()
    31 {
    32     cin>>n>>m;
    33     int a,b,c,d;
    34     for(int i=0;i<m;i++)
    35     {
    36         cin>>a>>b>>c>>d;
    37         edge[min(a,b)].push_back(Edge(max(a,b),c,d));
    38     }
    39 }
    40 
    41 void solve()
    42 {
    43     memset(f,false,sizeof(f));
    44     memset(g,false,sizeof(g));
    45     f[1][0]=true;
    46     g[1][0]=true;
    47     for(int i=1;i<=n;i++)
    48     {
    49         for(int j=0;j<MAX_T;j++)
    50         {
    51             if(f[i][j] || g[i][j])
    52             {
    53                 for(int k=0;k<edge[i].size();k++)
    54                 {
    55                     Edge temp=edge[i][k];
    56                     f[temp.dest][j+temp.c]|=f[i][j];
    57                     g[temp.dest][j+temp.d]|=g[i][j];
    58                 }
    59             }
    60         }
    61     }
    62     for(int i=0;i<MAX_T;i++)
    63     {
    64         if(f[n][i] && g[n][i])
    65         {
    66             ans=i;
    67             break;
    68         }
    69     }
    70 }
    71 
    72 void print()
    73 {
    74     if(ans==-1) cout<<"IMPOSSIBLE"<<endl;
    75     else cout<<ans<<endl;
    76 }
    77 
    78 int main()
    79 {
    80     read();
    81     solve();
    82     print();
    83 }
  • 相关阅读:
    相似数据检测算法
    从一个简单的程序中你能看到什么?(面向对象的真帝)
    如何更好的理解类和结构
    从一个很简单的文件上传来品味面向对象的大局观(抽象类和功能类)
    网站中的缩略图是如何生成的?(C#处理图像)
    进程间通信(一)
    POSIX线程-(六)
    进程间通信(四)
    进程间通信(三)
    POSIX线程-(五)
  • 原文地址:https://www.cnblogs.com/Leohh/p/7686249.html
Copyright © 2011-2022 走看看