Editorial for VOI 07 Bài 3 - Robot cứu hỏa
Remember to use this editorial only when stuck, and not to copy-paste code from it. Please be respectful to the problem author and editorialist.
Submitting an official solution before solving the problem yourself is a bannable offence.
Submitting an official solution before solving the problem yourself is a bannable offence.
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; }
Comments