省选模拟赛 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\n",ans);

    return 0;
}

 

posted @ 2018-04-03 16:53  zbtrs  阅读(250)  评论(0编辑  收藏  举报