题目描述
火星探险队的登陆舱将在火星表面着陆,登陆舱内有多部障碍物探测车。登陆舱着陆后,探测车将离开登陆舱向先期到达的传送器方向移动。探测车在移动中还必须采集岩石标本。每一块岩石标本由最先遇到它的探测车完成采集。每块岩石标本只能被采集一次。岩石标本被采集后,其他探测车可以从原来岩石标本所在处通过。探测车不能通过有障碍的地面。本题限定探测车只能从登陆处沿着向南或向东的方向朝传送器移动,而且多个探测车可以在同一时间占据同一位置。如果某个探测车在到达传送器以前不能继续前进,则该车所采集的岩石标本将全部损失。
用一个 P·Q 网格表示登陆舱与传送器之间的位置。登陆舱的位置在(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
给定每个位置的状态,计算探测车的最优移动方案,使到达传送器的探测车的数量最多,
而且探测车采集到的岩石标本的数量最多
输入输出格式
输入格式:
第 1行为探测车数,第 2 行为 P 的值,第3 行为Q 的值。接下来的 Q 行是表示登陆舱与传送器之间的位置状态的 P·Q 网格。用 3 个数字表示火星表面位置的状态:0 表示平坦无障碍,1表示障碍,2 表示石块。
输出格式:
每行包含探测车号和一个移动方向,0 表示向南移动,1 表示向东移动。
输入输出样例
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 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
说明
车数,P,Q<=35
考虑和方格取数一样,我们把一个方格下点拆成两个点。对于非障碍点,中间连一条费用为0流量为INF的边(可以走这里过但是不取走东西)。对于有石子的点,我们再连一条费用为1流量为1的边(只能取走一次)。注意费用流不能叠加,有石子的点既有非障碍点的连边又有自己的连边。把起点中间那条边的流量设为星球车的台数,跑最大费用流即可。
对于输出方案,我们记录每一个方格下点对应的中间边的反向边(快速获得该边增流的流量)。每一次在方格图上DFS,如果该点还有增流流量我们就走上去并且把该点增流流量减一。走K次就好了。
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int maxm = 100005, maxn = 105, maxp = maxn * maxn;
const int IN = 0, OUT = 1, inf = 0x3f3f3f3f;
int n, m, k;
struct edge {
int v, cost, w, next;
}e[maxm << 1];
int head[maxp], cnt, pos[maxn][maxn][2], mp[maxn][maxn], pcnt;
int st, ed, nxt[maxn][maxn][2], flow[maxn][maxn];
void adde(const int &u, const int &v, const int &w, const int &cost) {
e[++cnt] = (edge) {v, cost, w, head[u]};
head[u] = cnt;
e[++cnt] = (edge) {u, -cost, 0, head[v]};
head[v] = cnt;
}
int dis[maxp], vis[maxp], fa[maxp], eid[maxp], ans;
void SPFA(int s, int t) {
queue<int > q;
for(register int i = 0; i <= pcnt; ++i) dis[i] = -inf;
memset(vis, 0, sizeof(vis));
memset(fa, 0, sizeof(fa));
q.push(s), dis[s] = 0, vis[s] = 1;
while(!q.empty()) {
int u = q.front();
q.pop(), vis[u] = 0;
for(register int i = head[u]; i; i = e[i].next) {
if(!e[i].w) continue;
int v = e[i].v;
if(dis[v] < dis[u] + e[i].cost) {
dis[v] = dis[u] + e[i].cost;
fa[v] = u, eid[v] = i;
if(vis[v]) continue;
q.push(v), vis[v] = 1;
}
}
}
}
void ExtFlow(int s, int v, int & mn) {
if(v == s) return;
mn = min(e[eid[v]].w, mn);
ExtFlow(s, fa[v], mn);
e[eid[v]].w -= mn;
e[eid[v] ^ 1].w += mn;
ans += e[eid[v]].cost * mn;
}
int GetAns(int s, int t) {
int mn = inf;
while(1) {
SPFA(s, t);
if(dis[t] == -inf) break;
mn = inf, ExtFlow(s, t, mn);
}
return ans;
}
void print(int x, int y, int id) {
--flow[x][y];
if(x + 1 <= n && flow[x + 1][y]) printf("%d %d\n", id, 0), print(x + 1, y, id);
else if(y + 1 <= m && flow[x][y + 1]) printf("%d %d\n", id, 1), print(x, y + 1, id);
}
int main() {
scanf("%d%d%d", &k, &m, &n);
cnt = 1;
for(register int i = 1; i <= n; ++i)
for(register int j = 1; j <= m; ++j) {
scanf("%d", &mp[i][j]);
pos[i][j][IN] = ++pcnt;
pos[i][j][OUT] = ++pcnt;
if(i == 1 && j == 1) continue;
if(mp[i][j] == 1) continue;
adde(pos[i][j][IN], pos[i][j][OUT], inf, 0), nxt[i][j][0] = cnt;
if(mp[i][j] == 2)
adde(pos[i][j][IN], pos[i][j][OUT], 1, 1), nxt[i][j][1] = cnt;
}
for(register int i = 1; i < m; ++i) adde(pos[n][i][OUT], pos[n][i + 1][IN], inf, 0);
for(register int i = 1; i < n; ++i) adde(pos[i][m][OUT], pos[i + 1][m][IN], inf, 0);
for(register int i = 1; i < n; ++i)
for(register int j = 1; j < m; ++j) {
adde(pos[i][j][OUT], pos[i + 1][j][IN], inf, 0);
adde(pos[i][j][OUT], pos[i][j + 1][IN], inf, 0);
}
if(mp[1][1] == 2) adde(pos[1][1][IN], pos[1][1][OUT], k - 1, 0), adde(pos[1][1][IN], pos[1][1][OUT], 1, 1);
else adde(pos[1][1][IN], pos[1][1][OUT], k, 0);
st = pos[1][1][IN], ed = pos[n][m][OUT];
GetAns(st, ed);
for(register int i = 1; i <= n; ++i)
for(register int j = 1; j <= m; ++j)
flow[i][j] = e[nxt[i][j][0]].w + e[nxt[i][j][1]].w;
for(register int i = 1; i <= k; ++i)
print(1, 1, i);
return 0;
}
rockdu
没有帐号? 立即注册