火星探险问题
題目描述
火星探險隊的登陸艙將在火星表面著陸,登陸艙內(nèi)有多部障礙物探測車。登陸艙著陸后,探測車將離開登陸艙向先期到達(dá)的傳送器方向移動。探測車在移動中還必須采集巖石標(biāo)本。每一塊巖石標(biāo)本由最先遇到它的探測車完成采集。每塊巖石標(biāo)本只能被采集一次。巖石標(biāo)本被采集后,其他探測車可以從原來巖石標(biāo)本所在處通過。探測車不能通過有障礙的地面。本題限定探測車只能從登陸處沿著向南或向東的方向朝傳送器移動,而且多個探測車可以在同一時間占據(jù)同一位置。如果某個探測車在到達(dá)傳送器以前不能繼續(xù)前進(jìn),則該車所采集的巖石標(biāo)本將全部損失。
用一個 P·Q 網(wǎng)格表示登陸艙與傳送器之間的位置。登陸艙的位置在(X1,Y1)處,傳送器
的位置在(XP ,YQ)處。
X 1,Y 1 X 2 , Y 1 X 3 , Y 1 … X P-1, Y 1 X P , Y 1
X 1,Y 2 X 2 , Y 2 X 3 , Y 2 … X P-1, Y 2 X P , Y 2
X 1, Y 3 X 2 , Y 3 X 3 ,Y 3 … X P-1, Y 3 X P , Y 3
… …
X 1 ,Y Q-1 X 2 , Y Q-1 X 3 , Y Q-1 … X P-1, Y Q-1 X P , Y Q-1
X 1,Y Q X 2 , Y Q X 3 , Y Q … X P-1, Y Q X P ,Y Q
給定每個位置的狀態(tài),計算探測車的最優(yōu)移動方案,使到達(dá)傳送器的探測車的數(shù)量最多,
而且探測車采集到的巖石標(biāo)本的數(shù)量最多
輸入格式
第 1行為探測車數(shù),第 2 行為 P 的值,第3 行為Q 的值。接下來的 Q 行是表示登陸艙與傳送器之間的位置狀態(tài)的 P·Q 網(wǎng)格。用 3 個數(shù)字表示火星表面位置的狀態(tài):0 表示平坦無障礙,1表示障礙,2 表示石塊。
輸出格式
每行包含探測車號和一個移動方向,0 表示向南移動,1 表示向東移動。
輸入輸出樣例
輸入 #1 復(fù)制
2
10
8
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 1 1 0 0 0
0 0 0 1 0 2 0 0 0 0
1 1 0 1 2 0 0 0 0 1
0 1 0 0 2 0 1 1 0 0
0 1 0 1 0 0 1 1 0 0
0 1 2 0 0 0 0 1 0 0
0 0 0 0 0 0 0 0 0 0
輸出 #1 復(fù)制
1 1
1 1
1 1
1 1
1 0
1 0
1 1
1 1
1 1
1 1
1 0
1 0
1 1
1 0
1 0
1 0
2 1
2 1
2 1
2 1
2 0
2 0
2 0
2 0
2 1
2 0
2 0
2 1
2 0
2 1
2 1
2 1
說明/提示
車數(shù),P,Q<=35
因為每個石塊只會被采集一次,所以很明顯的拆點限制采集。但是當(dāng)時我寫的時候想到如果我們對于每個點,連出去的時候連一條流量為1,費用為(當(dāng)前點==石塊),再加一條流量為INF,費用為0的邊(很傻逼是吧。。。。。因為每個點會連出去兩次,所以可能被用兩次。。。。QAQ。。所以還是要拆點)。
AC代碼:
#pragma GCC optimize(2) #include<bits/stdc++.h> //#define int long long using namespace std; const int N=32000,M=1000010; const int inf=0x3f3f3f3f; int num,n,m,g[40][40],s,t,v[N],e[N],d[N],maxflow,base; int head[N],nex[M],to[M],w[M],flow[M],tot=1; inline void ade(int a,int b,int c,int d){to[++tot]=b; w[tot]=d; flow[tot]=c; nex[tot]=head[a]; head[a]=tot; } inline void add(int a,int b,int c,int d){ade(a,b,c,d); ade(b,a,0,-d); } inline int id(int x,int y){return (x-1)*m+y; } int spfa(){memset(d,0xcf,sizeof d); queue<int> q; q.push(s);int vis[N]={0}; d[s]=0; vis[s]=1;while(q.size()){int u=q.front(); q.pop(); vis[u]=0;for(int i=head[u];i;i=nex[i]){if(flow[i]&&d[to[i]]<d[u]+w[i]){d[to[i]]=d[u]+w[i];v[to[i]]=u; e[to[i]]=i;if(!vis[to[i]]) q.push(to[i]),vis[to[i]]=1;}}}return d[t]!=0xcfcfcfcf; } void EK(){while(spfa()){int mi=inf;for(int i=t;i!=s;i=v[i]) mi=min(mi,flow[e[i]]);for(int i=t;i!=s;i=v[i]) flow[e[i]]-=mi,flow[e[i]^1]+=mi; maxflow+=mi;} } void out(int p,int x){for(int i=head[x+base];i;i=nex[i]){if(flow[i^1]&&to[i]!=t&&x<to[i]){flow[i^1]--; cout<<p<<' ';if(to[i]==1+x) cout<<1<<endl; else cout<<0<<endl;return out(p,to[i]);}} } signed main(){cin>>num>>m>>n; s=0; t=2*n*m+1; add(s,1,num,0); base=n*m;for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){int x; cin>>x; if(x==1) continue;add(id(i,j),id(i,j)+base,1,x);add(id(i,j),id(i,j)+base,inf,0);if(i+1<=n) add(id(i,j)+base,id(i+1,j),inf,0);if(j+1<=m) add(id(i,j)+base,id(i,j+1),inf,0);}}add(id(n,m)+base,t,num,0);EK();for(int i=1;i<=maxflow;i++) out(i,1);return 0; }總結(jié)
- 上一篇: Codeforces Edu:双指针 »
- 下一篇: loj6225「网络流 24 题」火星探