Hướng dẫn giải của VOI 07 Bài 3 - Robot cứu hỏa
Chỉ dùng lời giải này khi không có ý tưởng, và đừng copy-paste code từ lời giải này. Hãy tôn trọng người ra đề và người viết lời giải.
Nộp một lời giải chính thức trước khi tự giải là một hành động có thể bị ban.
Nộp một lời giải chính thức trước khi tự giải là một hành động có thể bị ban.
Lưu ý: Các code mẫu dưới đây chỉ mang tính tham khảo và có thể không AC được bài tập này
Code mẫu của happyboy99x
#include<algorithm> #include<cstdio> #include<queue> #include<vector> using namespace std; typedef pair<int, int> ii; typedef vector<ii> vii; typedef vector<vii> vvii; typedef vector<int> vi; typedef vector<vi> vvi; #define fi first #define se second #define N 500 #define INF 1000000000 #define TR(v, it) for(typeof((v).begin()) it = (v).begin(); it != (v).end(); ++it) int gas[N], c[N][N], n, m; vvii g; vvi t; void enter() { scanf("%d",&n); for(int i = 0; i < n; ++i) scanf("%d", gas+i); scanf("%d",&m); g.resize(n); for(int i = 0; i < m; ++i) { int u, v, l, t; scanf("%d%d%d%d", &u, &v, &l, &t); --u; --v; c[u][v] = c[v][u] = t; g[u].push_back(ii(v, l)); g[v].push_back(ii(u, l)); } } void dijkstra() { t.resize(n); vi d = vi(n, INF); d[0] = 0; priority_queue<ii, vii, greater<ii> > qu; qu.push(ii(0, 0)); while(!qu.empty()) { int du = qu.top().fi, u = qu.top().se; qu.pop(); if(du > d[u]) continue; TR(g[u], it) { int v = it->fi, l = it->se; if(du + l < d[v]) { t[v] = vi(1, u); qu.push(ii(d[v] = du + l, v)); } else if(du + l == d[v]) t[v].push_back(u); } } } bool bfs(int w) { queue<ii> qu; qu.push(ii(n-1, w)); while(!qu.empty()) { int u = qu.front().fi, e = qu.front().se; qu.pop(); if(u == 0) return 1; TR(t[u], it) { int v = *it; if(c[u][v] <= e) qu.push(ii(v, gas[v] ? w : e - c[u][v])); } } return 0; } void calcW() { int lo = 0, hi = INF; while(lo < hi) { int mid = (lo+hi)/2; if(bfs(mid)) hi = mid; else lo = mid + 1; } printf("%d\n", lo); } int main() { #ifndef ONLINE_JUDGE freopen("input.txt", "r", stdin); #endif enter(); dijkstra(); calcW(); return 0; }
Code mẫu của ladpro98
#include <cstring> #include <vector> #include <queue> #include <list> #include <map> #include <set> #include <deque> #include <stack> #include <bitset> #include <algorithm> #include <functional> #include <numeric> #include <utility> #include <sstream> #include <iostream> #include <iomanip> #include <cstdio> #include <cmath> #include <cstdlib> #include <ctime> #include <memory.h> #include <cassert> #define FOR(i, a, b) for(int i = (a); i < (b); i++) #define REP(i, a, b) for(int i = (a); i <=(b); i++) #define FORD(i, a, b) for(int i = (a); i > (b); i--) #define REPD(i, a, b) for(int i = (a); i >=(b); i--) #define TR(it, a) for(typeof((a).begin()) it = (a).begin(); it != (a).end(); ++it) #define SZ(a) (int((a).size())) #define ALL(a) (a).begin(), (a).end() #define PB push_back #define MP make_pair #define LL long long #define LD long double #define II pair<int, int> #define X first #define Y second #define VI vector<int> const int N = 505; const int oo = 1000000009; using namespace std; int d1[N], dn[N]; bool recharge[N]; int n, m, limit, len; struct edge { int to, t, c; edge(int _v, int _t, int _c) { to = _v; t = _t; c = _c; } }; vector<edge> a[N]; void dijkstra(int source, int d[N]) { priority_queue<II, vector<II>, greater<II> > Q; Q.push(MP(0, source)); REP(i, 1, n) d[i] = oo; d[source] = 0; while (!Q.empty()) { int u = Q.top().Y, du = Q.top().X; Q.pop(); TR(it, a[u]) { int v = it -> to; int uv = it -> t; if (d[v] > d[u] + uv) { d[v] = d[u] + uv; Q.push(MP(d[v], v)); } } } } bool ok(int u, int d, int c) { if (u == n) return 1; if (recharge[u]) c = limit; TR(it, a[u]) { int v = it -> to; int tuv = it -> t; int cuv = it -> c; if (d + tuv + dn[v] == len && c >= cuv && ok(v, d + tuv, c - cuv)) return 1; } return 0; } int main() { ios :: sync_with_stdio(0); cin.tie(0); cin >> n; REP(i, 1, n) cin >> recharge[i]; cin >> m; int u, v, t, c; FOR(i, 0, m) { cin >> u >> v >> t >> c; a[u].PB(edge(v, t, c)); a[v].PB(edge(u, t, c)); } dijkstra(1, d1); dijkstra(n, dn); //REP(i, 1, n) cout << d1[i] << ' '; cout << endl; //REP(i, 1, n) cout << dn[i] << ' '; cout << endl; len = d1[n]; int l = 0, r = 1e9, ans; while (l <= r) { int mid = l + r >> 1; limit = mid; if (ok(1, 0, mid)) { ans = mid; r = mid - 1; } else l = mid + 1; } cout << ans; return 0; }
Code mẫu của RR
{$R+,Q+} uses math; const FINP=''; FOUT=''; MAXN=501; oo=5000001; type list=^node; node=record u:longint; next:list; end; var f1,f2:text; first,last,spt,hsize,n:longint; ke:array[1..MAXN] of list; c,t:array[1..MAXN,1..MAXN] of longint; queue,inq,hpos,h,a,d1,dn,e:array[1..MAXN] of longint; procedure openF; begin assign(f1,FINP); reset(f1); assign(f2,FOUT); rewrite(f2); end; procedure closeF; begin close(f1); close(f2); end; procedure add(u:longint; var a:list); var p:list; begin new(p); p^.u:=u; p^.next:=a; a:=p; end; procedure inp; var i,m,u,v:longint; begin read(f1,n); for i:=1 to n do read(f1,a[i]); read(f1,m); for i:=1 to m do begin read(f1,u,v,t[u,v],c[u,v]); t[v,u]:=t[u,v]; c[v,u]:=c[u,v]; add(u,ke[v]); add(v,ke[u]); end; end; procedure swap(var a,b:longint); var temp:longint; begin temp:=a; a:=b; b:=temp; end; procedure down1(i:longint); var j:longint; begin j:=i<<1; while (j<=hsize) do begin if (j<hsize) and (d1[h[j+1]]<d1[h[j]]) then inc(j); if (d1[h[j]]<d1[h[i]]) then begin swap(hpos[h[i]],hpos[h[j]]); swap(h[i],h[j]); end; i:=j; j:=i<<1; end; end; procedure up1(i:longint); var j:longint; begin j:=i>>1; while (i>1) and (d1[h[i]]<d1[h[j]]) do begin swap(hpos[h[i]],hpos[h[j]]); swap(h[i],h[j]); i:=j; j:=i>>1; end; end; procedure push1(u:longint); begin inc(hsize); h[hsize]:=u; hpos[u]:=hsize; up1(hsize); end; procedure pop1(var u:longint); begin u:=h[1]; hpos[u]:=0; swap(h[1],h[hsize]); hpos[h[1]]:=1; dec(hsize); down1(1); end; procedure left; var u,v:longint; p:list; begin for u:=2 to n do d1[u]:=oo; d1[1]:=0; hsize:=0; push1(1); while hsize>0 do begin pop1(u); p:=ke[u]; while p<>nil do begin v:=p^.u; p:=p^.next; if d1[v]>d1[u]+t[u,v] then begin d1[v]:=d1[u]+t[u,v]; if hpos[v]=0 then push1(v) else up1(hpos[v]); end; end; end; end; procedure down2(i:longint); var j:longint; begin j:=i<<1; while (j<=hsize) do begin if (j<hsize) and (dn[h[j+1]]<dn[h[j]]) then inc(j); if (dn[h[j]]<dn[h[i]]) then begin swap(hpos[h[i]],hpos[h[j]]); swap(h[i],h[j]); end; i:=j; j:=i<<1; end; end; procedure up2(i:longint); var j:longint; begin j:=i>>1; while (i>1) and (dn[h[i]]<dn[h[j]]) do begin swap(hpos[h[i]],hpos[h[j]]); swap(h[i],h[j]); i:=j; j:=i>>1; end; end; procedure push2(u:longint); begin inc(hsize); h[hsize]:=u; hpos[u]:=hsize; up2(hsize); end; procedure pop2(var u:longint); begin u:=h[1]; hpos[u]:=0; swap(h[1],h[hsize]); hpos[h[1]]:=1; dec(hsize); down2(1); end; procedure right; var v,u:longint; p:list; begin fillchar(hpos,sizeof(hpos),0); for u:=1 to n-1 do dn[u]:=oo; dn[n]:=0; hsize:=0; push2(n); while hsize>0 do begin pop2(u); p:=ke[u]; while p<>nil do begin v:=p^.u; p:=p^.next; if dn[v]>dn[u]+t[u,v] then begin dn[v]:=dn[u]+t[u,v]; if hpos[v]=0 then push2(v) else up2(hpos[v]); end; end; end; end; function check(w:longint):boolean; var u,v,x:longint; p:list; begin fillchar(inq,sizeof(inq),0); for u:=1 to n do e[u]:=-1; first:=1; last:=1; spt:=1; queue[1]:=1; e[1]:=w; inq[1]:=1; while spt>0 do begin u:=queue[first]; inc(first); if first=MAXN then first:=1; dec(spt); inq[u]:=0; p:=ke[u]; while p<>nil do begin v:=p^.u; p:=p^.next; if d1[u]+t[u,v]+dn[v]>d1[n] then continue; if e[u]<c[u,v] then continue; if a[v]=0 then x:=e[u]-c[u,v] else x:=w; if x>e[v] then begin e[v]:=x; if inq[v]=0 then begin inc(last); if last=MAXN then last:=1; queue[last]:=v; inc(spt); end; inq[v]:=1; end; end; end; check:=e[n]>=0; end; procedure solve; var u,l,r,mid:longint; begin l:=0; r:=oo; repeat mid:=(l+r)>>1; if check(mid) then r:=mid else l:=mid; until r-l<=1; if check(l) then writeln(f2,l) else writeln(f2,r); end; begin openF; inp; left; right; solve; closeF; end.
Code mẫu của khuc_tuan
#include <iostream> #include <vector> #include <queue> using namespace std; struct Node { int v, t, c; Node *next; }; int n; int mark[505]; Node * ke[505]; int F[505], G[505]; bool inq[505]; void add( Node * & p, int v, int t, int c) { Node * q = new Node; q->v = v; q->t = t; q->c = c; q->next = p; p = q; } int main() { scanf("%d", &n); for(int i=1;i<=n;++i) scanf("%d", mark+i); mark[1] = mark[n] = 1; int m; scanf("%d", &m); for(int i=0;i<m;++i) { int u, v, t, c; scanf("%d%d%d%d", &u, &v, &t, &c); add( ke[u], v, t, c); add( ke[v], u, t, c); } memset( F, 0x1f, sizeof(F)); F[1] = 0; queue<int> q; q.push(1); inq[1] = true; while(!q.empty()) { int u = q.front(); inq[u] = false; q.pop(); for(Node *p = ke[u]; p!=NULL; p = p->next) { int v = p->v; if(F[v]>F[u]+p->t) { F[v] = F[u] + p->t; if(!inq[v]) q.push(v), inq[v] = true; } } } int left = 0, right = 500 * 10000; while(left<right) { int mid = (left + right) / 2; memset( G, -1, sizeof(G)); G[1] = mid; queue<int> q; q.push(1); memset( inq, false, sizeof(inq)); inq[1] = true; while(!q.empty()) { int u = q.front(); inq[u] = false; q.pop(); for(Node *p = ke[u]; p!=NULL; p=p->next) { int v = p->v; if(F[v] == F[u] + p->t) { if(G[v]<G[u]-p->c) { G[v] = G[u] - p->c; if(mark[v]) G[v] = mid; if(!inq[v]) q.push(v), inq[v] = true; } } } } if(G[n]!=-1) right = mid; else left = mid + 1; } cout << left << endl; //system("pause"); return 0; }
Bình luận