uva 11380 - Down Went The Titanic (最大流)

该问题要求在考虑浮动冰块、水域、大冰山和安全木头等条件下,找出使最多人数幸存的策略。输入包含多个测试用例,每个用例描述了一个区域的X、Y尺寸和大木头的最大承载人数P,输出为每个测试用例的最大幸存者数。解题关键在于正确理解人们在安全地点可以停留直至救援船到达。

Problem D

Down Went The Titanic

Time Limit: 8 Second

 

After the collision of the great Titanic with the iceberg, it went down. Now there are peoples floating in the cold water struggling with death. Some helping ship will arrive to save them. But they have to survive until the ships arrive. Now consider a water area with people, floating ices, large woods etc. Consider the following symbols:

 

*          People staying on floating ice. People want to move from here as the floating ice cannot carry them for long time. Once a people move from here, the floating ice will get drowned. People can move to any of the four directions (north, east, west and south).

~          Water. People cannot go or move through them as water is extremely cold and not good enough for swimming.

.           Floating ice. People can move to a floating ice. But floating ices are so light that they cannot float for long time, so people should move from here as soon as possible and once a people move from here, the floating ice will get drowned.

@        Large iceberg. People can move here but cannot stay here as they are extremely cold. These icebergs will remain floating all the time. Note that, no two people can stay on floating ice or large iceberg at the same time.

#          Large wood. This place is safe. People can move and stay here until the helping ships arrive. A large wood will get drowned if more than P people stay on it at the same time.

 

Given the description of the area you have to find an optimal strategy that ensures the maximum number of living people.

 

Input:

The input contains a number of test cases. Each test case starts with a line containing three integers X, Y and P, where X, Y is the dimensions of the area (1 ≤ X, Y ≤ 30) and P (P ≤ 10) is the highest capacity of the large woods.  Next X lines each contains Y characters. These lines contain no blank spaces or any characters other than asterisk (*), tilde (~), dot (.), at (@) and hash (#). Not more than 50% of the total area has a people. Input will terminate with end of file (EOF). There is a blank line between two consecutive test cases.

 

Output:

For each test case print one line of output, an integer denoting the maximum number of survivors possible.

 

SAMPLE INPUT

OUTPUT FOR SAMPLE INPUT

3 4 2

*~~#

...@

.~.*

 

3 5 1

~~*~~

#.@.#

~~*~~

 

1 4 2

**#~

2

2

1

 

 

 

Problemsetter: Ishtiak Zaman

Special Thanks To: Md. Mahbubul Hasan

根据题目意思建图就可以了。开始错在误认为走到#上后就不会再移动了,实际上题目根本没有这样的条件。

#include <cstdio>
#include <algorithm>
#include <vector>
#include <map>
#include <queue>
#include <iostream>
#include <stack>
#include <set>
#include <cstring>
#include <stdlib.h>
#include <cmath>
using namespace std;
typedef long long LL;
typedef pair<int, int> P;
const int maxn = 2000 + 5;
const int maxm = 100;
const int INF = 1000000000;

struct Edge {
  int from, to, cap, flow;
};

struct Dinic {
  int n, m, s, t;
  vector<Edge> edges;    // 边数的两倍
  vector<int> G[maxn];   // 邻接表,G[i][j]表示结点i的第j条边在e数组中的序号
  bool vis[maxn];        // BFS使用
  int d[maxn];           // 从起点到i的距离
  int cur[maxn];         // 当前弧指针

  void ClearAll(int n) {
    for(int i = 0; i < n; i++) G[i].clear();
    edges.clear();
  }

  void ClearFlow() {
    for(int i = 0; i < edges.size(); i++) edges[i].flow = 0;
  }

  void AddEdge(int from, int to, int cap) {
    //cout << from << ' ' << to << ' ' << cap << endl;
    edges.push_back((Edge){from, to, cap, 0});
    edges.push_back((Edge){to, from, 0, 0});
    m = edges.size();
    G[from].push_back(m-2);
    G[to].push_back(m-1);
  }

  bool BFS() {
    memset(vis, 0, sizeof(vis));
    queue<int> Q;
    Q.push(s);
    vis[s] = 1;
    d[s] = 0;
    while(!Q.empty()) {
      int x = Q.front(); Q.pop();
      for(int i = 0; i < G[x].size(); i++) {
        Edge& e = edges[G[x][i]];
        if(!vis[e.to] && e.cap > e.flow) {
          vis[e.to] = 1;
          d[e.to] = d[x] + 1;
          Q.push(e.to);
        }
      }
    }
    return vis[t];
  }

  int DFS(int x, int a) {
    if(x == t || a == 0) return a;
    int flow = 0, f;
    for(int& i = cur[x]; i < G[x].size(); i++) {
      Edge& e = edges[G[x][i]];
      if(d[x] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap-e.flow))) > 0) {
        e.flow += f;
        edges[G[x][i]^1].flow -= f;
        flow += f;
        a -= f;
        if(a == 0) break;
      }
    }
    return flow;
  }

  int Maxflow(int s, int t) {
    this->s = s; this->t = t;
    int flow = 0;
    while(BFS()) {
      memset(cur, 0, sizeof(cur));
      flow += DFS(s, INF);
    }
    return flow;
  }
};

Dinic g;

char M[maxm][maxm];
int x, y;

int id(int i, int j){
    return (i-1)*y+j;
}

const int cx[] = {-1,0,1,0};
const int cy[] = {0,1,0,-1};

void expand(int nx, int ny, int pos){
    for(int i = 0;i < 4;i++){
        int tx = nx+cx[i];
        int ty = ny+cy[i];
        if(M[tx][ty] == '.' || M[tx][ty] == '@' || M[tx][ty] == '#'){
            g.AddEdge(pos, id(tx, ty), INF);
        }
    }
}

int main(){
    int p;
    while(scanf("%d%d%d", &x, &y, &p)!= EOF){
        g.ClearAll(x*y*2+2);
        int source = 0, sink = x*y*2+1;
        memset(M, -1, sizeof M);
        for(int i = 1;i <= x;i++){
            scanf("%s", M[i]+1);
        }
        for(int i = 1;i <= x;i++){
            for(int j = 1;j <= y;j++){
                if(M[i][j] == '*'){
                    expand(i, j, id(i, j));
                    g.AddEdge(source, id(i, j), 1);
                }
                else if(M[i][j] == '.'){
                    g.AddEdge(id(i, j), id(i, j)+x*y, 1);
                    expand(i, j, id(i, j)+x*y);
                }
                else if(M[i][j] == '@'){
                    expand(i, j, id(i, j));
                }
                else if(M[i][j] == '#'){
                    g.AddEdge(id(i, j), sink, p);
                    expand(i, j, id(i, j));
                }
            }
        }
        printf("%d\n", g.Maxflow(source, sink));
    }
    return 0;
}


六自由度机械臂ANN人工神经网络设计:正向逆向运动学求解、正向动力学控制、拉格朗日-欧拉法推导逆向动力学方程(Matlab代码实现)内容概要:本文档围绕六自由度机械臂的ANN人工神经网络设计展开,详细介绍了正向与逆向运动学求解、正向动力学控制以及基于拉格朗日-欧拉法推导逆向动力学方程的理论与Matlab代码实现过程。文档还涵盖了PINN物理信息神经网络在微分方程求解、主动噪声控制、天线分析、电动汽车调度、储能优化等多个工程与科研领域的应用案例,并提供了丰富的Matlab/Simulink仿真资源和技术支持方向,体现了其在多学科交叉仿真与优化中的综合性价值。; 适合人群:具备一定Matlab编程基础,从事机器人控制、自动化、智能制造、电力系统或相关工程领域研究的科研人员、研究生及工程师。; 使用场景及目标:①掌握六自由度机械臂的运动学与动力学建模方法;②学习人工神经网络在复杂非线性系统控制中的应用;③借助Matlab实现动力学方程推导与仿真验证;④拓展至路径规划、优化调度、信号处理等相关课题的研究与复现。; 阅读建议:建议按目录顺序系统学习,重点关注机械臂建模与神经网络控制部分的代码实现,结合提供的网盘资源进行实践操作,并参考文中列举的优化算法与仿真方法拓展自身研究思路。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值