P3356 火星探险问题

\(\color{#0066ff}{题目描述}\)

火星探险队的登陆舱将在火星表面着陆,登陆舱内有多部障碍物探测车。登陆舱着陆后,探测车将离开登陆舱向先期到达的传送器方向移动。探测车在移动中还必须采集岩石标本。每一块岩石标本由最先遇到它的探测车完成采集。每块岩石标本只能被采集一次。岩石标本被采集后,其他探测车可以从原来岩石标本所在处通过。探测车不能通过有障碍的地面。本题限定探测车只能从登陆处沿着向南或向东的方向朝传送器移动,而且多个探测车可以在同一时间占据同一位置。如果某个探测车在到达传送器以前不能继续前进,则该车所采集的岩石标本将全部损失。

用一个 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

给定每个位置的状态,计算探测车的最优移动方案,使到达传送器的探测车的数量最多,

而且探测车采集到的岩石标本的数量最多

\(\color{#0066ff}{输入格式}\)

第 1行为探测车数,第 2 行为 P 的值,第3 行为Q 的值。接下来的 Q 行是表示登陆舱与传送器之间的位置状态的 P·Q 网格。用 3 个数字表示火星表面位置的状态:0 表示平坦无障碍,1表示障碍,2 表示石块。

\(\color{#0066ff}{输出格式}\)

每行包含探测车号和一个移动方向,0 表示向南移动,1 表示向东移动。

\(\color{#0066ff}{输入样例}\)

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

\(\color{#0066ff}{输出样例}\)

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

\(\color{#0066ff}{数据范围与提示}\)

车数,P,Q<=35

有spj

\(\color{#0066ff}{题解}\)

拆点,跑最小费用最大流

起点跟1,1连,重点跟最后连

自己的入点出点连在一起,如果有石子,还得在连一条容量为1,边权为1的边,石子只能获得一次

对于障碍点,什么都不用连

#include <bits/stdc++.h>
#define LL long long
LL in() 
{
	char ch; LL x = 0, f = 1;
	while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
	while(isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar();
	return x * f;
}
struct node 
{
	int to, dis, can;
	node *nxt, *rev;
	node(int to = 0, int dis = 0, int can = 0, node *nxt = NULL):to(to), dis(dis), can(can), nxt(nxt) {}
	void *operator new (size_t) 
	{
		static node *S = NULL, *T = NULL;
		return (S == T) && (T = (S = new node[1024]) + 1024), S++;
	}
};
const int maxn = 100050;
const int inf = 0x7fffffff;
int n, p, q, s, t;
typedef node* nod;
nod head[maxn], road[maxn];
int dis[maxn], change[maxn];
bool vis[maxn];
int id[55][55], mp[55][55];
std::queue<int> V;
void add(int from, int to, int can, int dis) 
{
	nod o = new node(to, dis, can, head[from]);
	head[from] = o;
}
void link(int from, int to, int can, int dis) 
{
	add(from, to, can, dis);
	add(to, from, 0, -dis);
	head[from]->rev = head[to];
	head[to]->rev = head[from];
}
bool bfs() 
{
	for(int i = s; i <= t; i++) change[i] = inf, dis[i] = -inf;
	V.push(s);
	dis[s] = 0;
	while(!V.empty())
	{
		int tp = V.front(); V.pop();
		vis[tp] = false;
		for(nod i = head[tp]; i; i = i->nxt) 
			if(dis[i->to] < dis[tp] + i->dis && i->can > 0) 
			{
				dis[i->to] = dis[tp] + i->dis;
				change[i->to] = std::min(change[tp], i->can);
				road[i->to] = i;
				if(!vis[i->to]) vis[i->to] = true, V.push(i->to);
			}
	}
	return change[t] != inf;
}
void mcmf() 
{
	while(bfs()) 
	{
		for(int o = t; o != s; o = road[o]->rev->to) 
		{
			road[o]->can -= change[t];
			road[o]->rev->can += change[t];
		}
	}
}
int nxt(int pos) 
{
	for(nod i = head[pos]; i; i = i->nxt) 
		if(i->to >= id[1][1] + id[p][q] && i->to <= id[p][q] + id[p][q] && i->rev->can > 0) return i->rev->can--, i->to - id[p][q];
	return 0;
}
void print(int pos) 
{
	int now = id[1][1];
	while(1) 
	{
		int go = nxt(now);
		if(go == now + 1) printf("%d 1\n", pos);
		else printf("%d 0\n", pos);
		now = go;
		if(now == id[p][q]) break;
	}
}
int main() 
{
	n = in(), q = in(), p = in();
	for(int cnt = 0, i = 1; i <= p; i++)
		for(int j = 1; j <= q; j++)
			id[i][j] = ++cnt, mp[i][j] = in();
	s = 0, t = (id[p][q] << 1) + 1;
	link(s, id[1][1], n, 0);
	link(id[p][q] << 1, t, n, 0);
	for(int i = 1; i <= p; i++) 
		for(int j = 1; j <= q; j++) 
		{
			if(mp[i][j] == 1) continue;
			link(id[i][j] + id[p][q], id[i][j], inf, 0);
			if(mp[i][j] == 2) link(id[i][j] + id[p][q], id[i][j], 1, 1);
			if(i + 1 <= p) 
				link(id[i][j], id[i + 1][j] + id[p][q], inf, 0);
			if(j + 1 <= q)
				link(id[i][j], id[i][j + 1] + id[p][q], inf, 0);
		}
	mcmf();
	for(int i = 1; i <= n; i++) print(i);
	return 0;
}
posted @ 2018-12-17 19:42  olinr  阅读(162)  评论(0编辑  收藏  举报