zoukankan      html  css  js  c++  java
  • 省选模拟赛 cti

    3 cti (cti.cpp/in/out, 1s, 512MB)
    3.1 Description
    有一个 n × m 的地图, 地图上的每一个位置可以是空地, 炮塔或是敌人. 你需要操纵炮塔消灭
    敌人.
    对于每个炮塔都有一个它可以瞄准的方向, 你需要在它的瞄准方向上确定一个它的攻击位置,
    当然也可以不进行攻击. 一旦一个位置被攻击, 则在这个位置上的所有敌人都会被消灭.
    保证对于任意一个炮塔, 它所有可能的攻击位置上不存在另外一个炮塔.
    定义炮弹的运行轨迹为炮弹的起点和终点覆盖的区域. 你需要求出一种方案, 使得没有两条炮
    弹轨迹相交.
    3.2 Input Format
    第一行两个整数 n,m.
    接下来 n 行, 每行 m 个整数, 0 表示空地, −1,−2,−3,−4 分别表示瞄准上下左右的炮塔, 正整
    数 p 表示表示此位置有 p 个敌人.
    3.3 Output Format
    一行一个整数表示答案.
    3.4 Sample 1
    3.4.1 Input
    3 2
    0 9
    -4 3
    0 -1
    3.4.2 Output
    9
    3.5 Sample 2
    3.5.1 Input
    4 5
    0 0 -2 0 0
    -4 0 5 4 0
    0 -4 3 0 6
    9 0 0 -1 0
    3.5.2 Output
    12

    3.6 Constraints
    对于前 20% 的数据, n,m ≤ 5;
    对于另 20% 的数据, 朝向上下的炮塔至多有 2 个;
    对于另 20% 的数据, 至多有 6 个炮塔;
    对于 100% 的数据, 1 ≤ n,m ≤ 50, 每个位置的敌人数量 < 1000.

    分析:将题目看作炮塔和敌人“匹配”,就和比特板这道题几乎一模一样了.

       需要注意的是炮塔可以不攻击任何敌人,那么连inf的边实际上就是连0边. 

    #include <cstdio>
    #include <queue>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    const int maxn = 55 * 55,inf = 0x7fffffff;
    int n,m,ans,a[55][55],cnt,cnt1,cnt2,S,T,pos[maxn][maxn],head[100010],to[100010],nextt[100010],w[100010],tot = 2;
    int d[100010];
    struct node
    {
        int x,y,opt;
    } shu[maxn],heng[maxn];
    
    void add(int x,int y,int z)
    {
        //cout << x << " " << y << " " << 1000 - z << endl;
        w[tot] = z;
        to[tot] = y;
        nextt[tot] = head[x];
        head[x] = tot++;
    
        w[tot] = 0;
        to[tot] = x;
        nextt[tot] = head[y];
        head[y] = tot++;
    }
    
    bool bfs()
    {
        queue <int> q;
        q.push(S);
        memset(d,-1,sizeof(d));
        d[S] = 0;
        while (!q.empty())
        {
            int u = q.front();
            q.pop();
            if (u == T)
                return true;
            for (int i = head[u];i;i = nextt[i])
            {
                int v = to[i];
                if (w[i] && d[v] == -1)
                {
                    d[v] = d[u] + 1;
                    q.push(v);
                }
            }
        }
        return false;
    }
    
    int dfs(int u,int f)
    {
        if (u == T)
            return f;
        int res = 0;
        for (int i = head[u];i;i = nextt[i])
        {
            int v = to[i];
            if (d[v] == d[u] + 1 && w[i])
            {
                int temp = dfs(v,min(f - res,w[i]));
                w[i] -= temp;
                w[i ^ 1] += temp;
                res += temp;
                if (res == f)
                    return res;
            }
        }
        if (!res)
            d[u] = -1;
        return res;
    }
    
    void dinic()
    {
        while (bfs())
            ans -= dfs(S,inf);
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= m; j++)
            {
                scanf("%d",&a[i][j]);
                if (a[i][j] < 0)
                {
                    if (a[i][j] == -1 || a[i][j] == -2)
                    {
                        node temp;
                        temp.x = i;
                        temp.y = j;
                        temp.opt = a[i][j];
                        shu[++cnt1] = temp;
                    }
                    else
                    {
                        node temp;
                        temp.x = i;
                        temp.y = j;
                        temp.opt = a[i][j];
                        heng[++cnt2] = temp;
                    }
                }
            }
        for (int i = 1; i <= cnt1; i++)
        {
            if (shu[i].opt == -1)
                for (int j = 1; j <= shu[i].x; j++)
                    pos[i][j] = ++cnt;
            else
                for (int j = 1; j <= n - shu[i].x + 1; j++)
                    pos[i][j] = ++cnt;
        }
        for (int i = 1; i <= cnt2; i++)
        {
            if (heng[i].opt == -3)
                for (int j = 1; j <= heng[i].y; j++)
                    pos[i + cnt1][j] = ++cnt;
            else
                for (int j = 1; j <= m - heng[i].y + 1; j++)
                    pos[i + cnt1][j] = ++cnt;
        }
        ans = 1000 * (cnt1 + cnt2);
        S = ++cnt;
        T = ++cnt;
        for (int i = 1; i <= cnt1; i++)
        {
            if (shu[i].opt == -1)
            {
                for (int j = 1; j <= shu[i].x; j++)
                {
                    if (j != shu[i].x)
                        add(pos[i][j],pos[i][j + 1],1000 - a[shu[i].x - j][shu[i].y]);
                    else
                        add(pos[i][j],T,1000);
                    if (j == 1)
                        add(S,pos[i][j],1000);
                }
            }
            else
            {
                for (int j = 1; j <= n - shu[i].x + 1; j++)
                {
                    if (j != n - shu[i].x + 1)
                        add(pos[i][j],pos[i][j + 1],1000 - a[shu[i].x + j][shu[i].y]);
                    else
                        add(pos[i][j],T,1000);
                    if (j == 1)
                        add(S,pos[i][j],1000);
                }
            }
        }
        for (int i = 1; i <= cnt2; i++)
        {
            if (heng[i].opt == -3)
            {
                for (int j = 1; j <= heng[i].y; j++)
                {
                    if (j != heng[i].y)
                        add(pos[i + cnt1][j],pos[i + cnt1][j + 1],1000 - a[heng[i].x][j]);
                    else
                        add(pos[i + cnt1][j],T,1000);
                    if (j == 1)
                        add(S,pos[i + cnt1][j],1000);
                }
            }
            else
            {
                for (int j = 1; j <= m - heng[i].y + 1; j++)
                {
                    if (j != m - heng[i].y + 1)
                        add(pos[i + cnt1][j],pos[i + cnt1][j + 1],1000 - a[heng[i].x][m - j + 1]);
                    else
                        add(pos[i + cnt1][j],T,1000);
                    if (j == 1)
                        add(S,pos[i + cnt1][j],1000);
                }
            }
        }
        for (int i = 1; i <= cnt1; i++)
            for (int j = 1; j <= cnt2; j++)
            {
                int X,Y;
                if (shu[i].opt == -1 && heng[j].opt == -4) //上右
                {
                    if (shu[i].x < heng[j].x || shu[i].y < heng[j].y)
                        continue;
                    X = heng[j].x;
                    Y = shu[i].y;
                    int temp1 = shu[i].x - X;
                    int temp2 = m - Y + 2;
                    add(pos[i][temp1],pos[j + cnt1][temp2],1000);
                }
                if (shu[i].opt == -1 && heng[j].opt == -3) //上左
                {
                    if (shu[i].x < heng[j].x || shu[i].y > heng[j].y)
                        continue;
                    X = heng[j].x;
                    Y = shu[i].y;
                    int temp1 = shu[i].x - X;
                    int temp2 = Y + 1;
                    add(pos[i][temp1],pos[j + cnt1][temp2],1000);
                }
                if (shu[i].opt == -2 && heng[j].opt == -4) //下右
                {
                    if (shu[i].y < heng[j].y || shu[i].x > heng[j].x)
                        continue;
                    X = heng[j].x;
                    Y = shu[i].y;
                    int temp1 = X - shu[i].x;
                    int temp2 = m - Y + 2;
                    add(pos[i][temp1],pos[j + cnt1][temp2],1000);
                }
                if (shu[i].opt == -2 && heng[j].opt == -3) //下左
                {
                    if (shu[i].x > heng[j].x || shu[i].y > heng[j].y)
                        continue;
                    X = heng[j].x;
                    Y = shu[i].y;
                    int temp1 = X - shu[i].x;
                    int temp2 = Y + 1;
                    add(pos[i][temp1],pos[j + cnt1][temp2],1000);
                }
            }
        dinic();
        printf("%d
    ",ans);
    
        return 0;
    }
  • 相关阅读:
    NOIP2018游记-DAY1
    NOIP2018游记-DAY0
    18.11.7绍一模拟赛
    [SPOJ]SELTEAM
    18.11.5绍一模拟赛
    18.11.2绍一模拟赛
    [模拟赛]世界杯
    [模拟赛]路途
    乘法逆元的研究
    子查询,TOP_N,分页,行转列
  • 原文地址:https://www.cnblogs.com/zbtrs/p/8709536.html
Copyright © 2011-2022 走看看