zoukankan      html  css  js  c++  java
  • 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
    ", pos);
    		else printf("%d 0
    ", 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;
    }
    
  • 相关阅读:
    【转】java正则表达式
    NDK学习笔记-使用现有so动态库
    NDK学习笔记-增量更新
    NDK学习笔记-增量更新
    NDK学习笔记-文件的拆分与合并
    NDK学习笔记-文件的拆分与合并
    NDK学习笔记-NDK开发流程
    NDK学习笔记-NDK开发流程
    NDK学习笔记-JNI的引用
    NDK学习笔记-JNI的引用
  • 原文地址:https://www.cnblogs.com/olinr/p/10133418.html
Copyright © 2011-2022 走看看