zoukankan      html  css  js  c++  java
  • 题解 P6005 【[USACO20JAN]Time is Mooney G】

    抢第一篇题解

    这题的思路其实就是一个非常简单的dijkstra,如果跑到第一个点的数据不能更新的时候就输出

    很多人不知道要跑多少次才停.其实这题因为答案要减去 T*c^2,而每条边的值 <= 1000,稍微推一下就可以发现这个程序最多跑1000次.

    所以,简单暴力的做法就是暴力写1000次dijkstra (01dij或者二维1000*1000都可以).这个方法当然可以优化,但是没有超时谁理他呢

    现在剩下一个小问题(如果没有经过的点,我们不能更新连同他的路).那么怎么办呢?

    摆在眼前的路有两条.第一:到所有点的初始值设成-1跑.如果目前的点的值为-1就证明他没有被经过,所以需要跳过

    第二:做一个vis,记录每次经过并且以前没有经过过的点.这里我用的是queue,记录所有这一次被拿到的点.

    注意不要马上更新,因为如果你马上更新就会出现没有经过的点被更新了

    01的意义就是保证所有点更新的都是之前更新过但这一次没有更新的,保证不会出现一条边被更新很多次的情况

    话不多说,上代码

    #include <iostream>
    #include <algorithm>
    #include <math.h>
    #include <queue>
    using namespace std;
    int dp[1005][2],head[100005],tot = 0,n,m,c, cost[1005],ans=0,vis[1005];
    struct Edge{
      int from, to,next;
    }edge[100005];
    void add(int f,int t){
      edge[++tot].from = f;
      edge[tot].to = t;
      edge[tot].next = head[f];
      head[f] = tot;
    }
    void setIO(string name) {
    	freopen((name+".in").c_str(),"r",stdin);
    	freopen((name+".out").c_str(),"w",stdout);
    	ios_base::sync_with_stdio(0);
    }
    //以上不解释
    void dij(int curr){
      queue<int> q;//记经过的边
      for (int i=1;i<=n;i++){
        if (!vis[i]) continue;//如果没有经过就不跑
        for (int j=head[i];j;j=edge[j].next){
          if (!vis[edge[j].to]) q.push(edge[j].to);//没经过就加进queue待会更新
          dp[edge[j].to][curr%2] = max(dp[edge[j].from][(curr+1)%2]+cost[edge[j].to],dp[edge[j].to][curr%2]);
          //要去的点的值现在的点的值+那个点的权值.
        }
      }
      while(!q.empty()){vis[q.front()] = true;q.pop();}
      //将所有经过的点的vis设成true
      ans = max(ans,(int)(dp[1][curr%2]-c*pow(curr,2)));
      //更新答案
    }
    
    int main(){
      // setIO("time");
      cin >> n >> m >> c;
      for (int i=1;i<=n;i++) cin >> cost[i];
      for (int i=0;i<m;i++){
        int a,b; cin >> a >> b;
        add(a,b);//连边,如果要转化为权值问题只需将权值设为cost[b]就行
      }
      vis[1] = true;//将初始点设为已经过
      for (int i=1;i<1000;i++){
        dij(i);//跑1000次
      }
      cout << ans;//输出
    }
    
    
  • 相关阅读:
    消息中间件(一)MQ详解及四大MQ比较
    SIP协议
    PAT (Basic Level) Practice 1008 数组元素循环右移问题
    LeetCode-Algorithms 1. 两数之和
    PAT (Basic Level) Practice 1040 有几个PAT
    PAT (Basic Level) Practice 1023 组个最小数
    PAT (Basic Level) Practice 1021 个位数统计
    PAT (Basic Level) Practice 1007 素数对猜想
    PAT (Basic Level) Practice 1006 换个格式输出整数
    PAT (Basic Level) Practice 1004 成绩排名
  • 原文地址:https://www.cnblogs.com/DannyXu/p/12232731.html
Copyright © 2011-2022 走看看