http://codeforces.com/gym/101617/attachments
题意:
给出一个图,每个顶点代表一个金矿,每个金矿有g和d两个值,g代表金矿初始的金子量,d是该金矿每天的金子量会减少d。顶点与顶点之间存在边,意思是从一个金矿到另一个金矿需要花费的天数。现在有个人一开始在1金矿,问最多能挖到多少金矿,注意,不能在一个金矿连续挖几天。
思路:
bfs求解,但是需要剪枝,用二位数组d[v][day]记录第day天时在v金矿所能获得的最大值。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<queue> 5 using namespace std; 6 const int maxn = 1000+5; 7 8 int tot,n,m,mx,ans; 9 int head[maxn]; 10 int g[maxn],d[maxn]; 11 int dis[maxn][maxn]; 12 13 struct Node 14 { 15 int v,w,next; 16 }e[2*maxn]; 17 18 struct node 19 { 20 int id; 21 int val; 22 int day; 23 bool operator< (const node& rhs) const 24 { 25 return day>rhs.day; 26 } 27 }; 28 29 void addEdge(int u,int v,int w) 30 { 31 e[tot].v = v; 32 e[tot].w = w; 33 e[tot].next = head[u]; 34 head[u] = tot++; 35 } 36 37 void bfs() 38 { 39 memset(dis,0,sizeof(dis)); 40 priority_queue<node> q; 41 node p; 42 p.id = 1; 43 p.val = g[1]; 44 p.day = 1; 45 q.push(p); 46 ans = g[1]; 47 48 dis[1][1] = g[1]; 49 while(!q.empty()) 50 { 51 p = q.top(); q.pop(); 52 int u = p.id; 53 54 for(int i=head[u];i!=-1;i=e[i].next) 55 { 56 int v = e[i].v; 57 int w = e[i].w; 58 node tmp = p; 59 tmp.id = v; 60 tmp.val += max(0,g[v]-d[v]*(p.day+w-1)); 61 tmp.day = p.day + w; 62 if(tmp.day>mx) continue; 63 if(tmp.val<=dis[v][tmp.day]) continue; 64 dis[v][tmp.day] = tmp.val; 65 q.push(tmp); 66 ans = max(ans,tmp.val); 67 } 68 69 } 70 } 71 72 int main() 73 { 74 //freopen("in.txt","r",stdin); 75 while(~scanf("%d%d",&n,&m)) 76 { 77 mx = 0; 78 tot = 0; 79 memset(head,-1,sizeof(head)); 80 for(int i=1;i<=n;i++) 81 { 82 scanf("%d%d",&g[i],&d[i]); 83 mx = max(mx,g[i]/d[i]+1); 84 } 85 while(m--) 86 { 87 int u,v,w; 88 scanf("%d%d%d",&u,&v,&w); 89 addEdge(u,v,w); 90 addEdge(v,u,w); 91 } 92 bfs(); 93 printf("%d ",ans); 94 } 95 return 0; 96 }