Gym 101617Jbfs+优先队列

来源:互联网 发布:异世界淘宝女王txt 编辑:程序博客网 时间:2024/05/17 20:28

Gym 101617J

题意:

​ n个金矿,每一个金矿都有一个初始值代表第一天里面所含的金子数量,每天减少di,现在从金矿1出发,问最多能获得多少金子。

思路:

​ 用bfs的方式思考,对于每一个状态就是沿着路径暴力搜索,利用bfs层的思想,对于采金矿的时间也是合理的,但是这样会超时,所以需要用到优化。

1. 对于时间有一个最大的时间,可以通过输入算出2. 对于某一个金矿的到达存在不同的方式,记录到达的时间和获得的金子数量,每次判断是否是最优。3. 对于金矿查找的时候按照时间的顺序从小到大排列,每次优先选择时间早的可以避免很多计算。
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <queue>using namespace std;const int maxn = 1005;int n,m;int ans;int dp[maxn][maxn];int d[maxn],v[maxn];int head[maxn],pos;int Mday;struct Node{    int to,v,next;}edge[maxn*2];struct Gold{    int now;    int val;    int day;    bool operator<(const Gold& b)const    {        return day>b.day;    }};void add_edge(int u,int v,int w){    edge[pos].to = v;    edge[pos].v = w;    edge[pos].next = head[u];    head[u] = pos++;}void bfs(){    priority_queue<Gold>Q;    Gold a;    a.day = 1;    a.now = 1;    a.val = v[1];    Q.push(a);    ans = v[1];    dp[1][1] = v[1];    while(!Q.empty()) {        Gold t1 = Q.top();        Q.pop();        int u = t1.now;        for(int i = head[u];i != -1; i = edge[i].next) {            int to = edge[i].to;            Gold temp = t1;            temp.day = t1.day + edge[i].v;            temp.now = to;            temp.val += max(0,v[to]-d[to]*(t1.day+edge[i].v-1));            if(temp.day > Mday) continue;            if(temp.val <= dp[to][temp.day]) continue;            Q.push(temp);            dp[to][temp.day] = temp.val;            ans = max(ans,temp.val);        }    }}int main(){//    freopen("in.txt","r",stdin);    memset(head,-1,sizeof(head));    memset(dp,0,sizeof(dp));    ans = 0;    scanf("%d%d",&n,&m);    Mday = 0;    for(int i = 1;i <= n; i++) {        scanf("%d%d",&v[i],&d[i]);        Mday = max(Mday,v[i]/d[i]+1);    }    pos = 0;    for(int i = 1;i <= m; i++) {        int u,v,w;        scanf("%d%d%d",&u,&v,&w);        add_edge(u,v,w);        add_edge(v,u,w);    }    bfs();    printf("%d\n",ans);    return 0;}
原创粉丝点击