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 = * ,inf = 0x7fffffff;
int n,m,ans,a[][],cnt,cnt1,cnt2,S,T,pos[maxn][maxn],head[],to[],nextt[],w[],tot = ;
int d[];
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] = ;
to[tot] = x;
nextt[tot] = head[y];
head[y] = tot++;
} bool bfs()
{
queue <int> q;
q.push(S);
memset(d,-,sizeof(d));
d[S] = ;
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] == -)
{
d[v] = d[u] + ;
q.push(v);
}
}
}
return false;
} int dfs(int u,int f)
{
if (u == T)
return f;
int res = ;
for (int i = head[u];i;i = nextt[i])
{
int v = to[i];
if (d[v] == d[u] + && w[i])
{
int temp = dfs(v,min(f - res,w[i]));
w[i] -= temp;
w[i ^ ] += temp;
res += temp;
if (res == f)
return res;
}
}
if (!res)
d[u] = -;
return res;
} void dinic()
{
while (bfs())
ans -= dfs(S,inf);
} int main()
{
scanf("%d%d",&n,&m);
for (int i = ; i <= n; i++)
for (int j = ; j <= m; j++)
{
scanf("%d",&a[i][j]);
if (a[i][j] < )
{
if (a[i][j] == - || a[i][j] == -)
{
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 = ; i <= cnt1; i++)
{
if (shu[i].opt == -)
for (int j = ; j <= shu[i].x; j++)
pos[i][j] = ++cnt;
else
for (int j = ; j <= n - shu[i].x + ; j++)
pos[i][j] = ++cnt;
}
for (int i = ; i <= cnt2; i++)
{
if (heng[i].opt == -)
for (int j = ; j <= heng[i].y; j++)
pos[i + cnt1][j] = ++cnt;
else
for (int j = ; j <= m - heng[i].y + ; j++)
pos[i + cnt1][j] = ++cnt;
}
ans = * (cnt1 + cnt2);
S = ++cnt;
T = ++cnt;
for (int i = ; i <= cnt1; i++)
{
if (shu[i].opt == -)
{
for (int j = ; j <= shu[i].x; j++)
{
if (j != shu[i].x)
add(pos[i][j],pos[i][j + ], - a[shu[i].x - j][shu[i].y]);
else
add(pos[i][j],T,);
if (j == )
add(S,pos[i][j],);
}
}
else
{
for (int j = ; j <= n - shu[i].x + ; j++)
{
if (j != n - shu[i].x + )
add(pos[i][j],pos[i][j + ], - a[shu[i].x + j][shu[i].y]);
else
add(pos[i][j],T,);
if (j == )
add(S,pos[i][j],);
}
}
}
for (int i = ; i <= cnt2; i++)
{
if (heng[i].opt == -)
{
for (int j = ; j <= heng[i].y; j++)
{
if (j != heng[i].y)
add(pos[i + cnt1][j],pos[i + cnt1][j + ], - a[heng[i].x][j]);
else
add(pos[i + cnt1][j],T,);
if (j == )
add(S,pos[i + cnt1][j],);
}
}
else
{
for (int j = ; j <= m - heng[i].y + ; j++)
{
if (j != m - heng[i].y + )
add(pos[i + cnt1][j],pos[i + cnt1][j + ], - a[heng[i].x][m - j + ]);
else
add(pos[i + cnt1][j],T,);
if (j == )
add(S,pos[i + cnt1][j],);
}
}
}
for (int i = ; i <= cnt1; i++)
for (int j = ; j <= cnt2; j++)
{
int X,Y;
if (shu[i].opt == - && heng[j].opt == -) //上右
{
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 + ;
add(pos[i][temp1],pos[j + cnt1][temp2],);
}
if (shu[i].opt == - && heng[j].opt == -) //上左
{
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 + ;
add(pos[i][temp1],pos[j + cnt1][temp2],);
}
if (shu[i].opt == - && heng[j].opt == -) //下右
{
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 + ;
add(pos[i][temp1],pos[j + cnt1][temp2],);
}
if (shu[i].opt == - && heng[j].opt == -) //下左
{
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 + ;
add(pos[i][temp1],pos[j + cnt1][temp2],);
}
}
dinic();
printf("%d\n",ans); return ;
}

省选模拟赛 cti的更多相关文章

  1. 【洛谷比赛】[LnOI2019]长脖子鹿省选模拟赛 T1 题解

    今天是[LnOI2019]长脖子鹿省选模拟赛的时间,小编表示考的不怎么样,改了半天也只会改第一题,那也先呈上题解吧. T1:P5248 [LnOI2019SP]快速多项式变换(FPT) 一看这题就很手 ...

  2. @省选模拟赛03/16 - T3@ 超级树

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 一棵 k-超级树(k-SuperTree) 可按如下方法得到:取 ...

  3. 3.28 省选模拟赛 染色 LCT+线段树

    发现和SDOI2017树点涂色差不多 但是当时这道题模拟赛的时候不会写 赛后也没及时订正 所以这场模拟赛的这道题虽然秒想到了LCT和线段树但是最终还是只是打了暴力. 痛定思痛 还是要把这道题给补了. ...

  4. 省选模拟赛第四轮 B——O(n^4)->O(n^3)->O(n^2)

    一 稍微转化一下,就是找所有和原树差距不超过k的不同构树的个数 一个挺trick的想法是: 由于矩阵树定理的行列式的值是把邻接矩阵数值看做边权的图的所有生成树的边权乘积之和 那么如果把不存在于原树中的 ...

  5. NOI2019省选模拟赛 第五场

    爆炸了QAQ 传送门 \(A\) \(Mas\)的童年 这题我怎么感觉好像做过--我记得那个时候还因为没有取\(min\)结果\(100\to 0\)-- 因为是个异或我们肯定得按位考虑贡献了 把\( ...

  6. NOI2019省选模拟赛 第六场

    传送门 又炸了-- \(A\) 唐时月夜 不知道改了什么东西之后就\(A\)掉了\(.jpg\) 首先,题目保证"如果一片子水域曾经被操作过,那么在之后的施法中,这片子水域也一定会被操作&q ...

  7. 省选模拟赛 arg

    1 arg (arg.cpp/in/out, 1s, 512MB)1.1 Description给出一个长度为 m 的序列 A, 请你求出有多少种 1...n 的排列, 满足 A 是它的一个 LIS. ...

  8. 5.10 省选模拟赛 拍卖 博弈 dp

    LINK:拍卖 比赛的时候 前面时间浪费的有点多 写这道题的时候 没剩多少时间了. 随便设了一个状态 就开始做了. 果然需要认真的思考.其实 从我的状态的状态转移中可以看出所有的结论. 这里 就不再赘 ...

  9. 5.5 省选模拟赛 B Permutation 构造 贪心

    LINK:Permutation 对于这种构造神题 我自然是要补的.为啥就我没想出来哇. 30分还是很好写的 注意8!实际上很小 不需要爆搜 写bfs记录状态即可.至于判断状态是否出现与否 可以开ma ...

随机推荐

  1. python的多路复用实现聊天群

    在我的<python高级编程和异步io编程>中我讲解了socket编程,这里贴一段用socket实现聊天室的功能的源码,因为最近工作比较忙,后期我会将这里的代码细节分析出来,目前先把代码贴 ...

  2. 关于手机端h5上传图片配合exif.min.js,processImg.js的使用

    首先这里有个new FileReader()的概念,这是h5新增的,用来把文件读入内存,并且读取文件中的数据.FileReader接口提供了一个异步API,使用该API可以在浏览器主线程中异步访问文件 ...

  3. “Hello World!”团队第五周第七次会议

    博客内容: 一.会议时间 二.会议地点 三.会议成员 四.会议内容 五.todo list 六.会议照片 七.燃尽图 八.checkout&push代码 一.会议时间 2017年11月16日  ...

  4. TeamWork#1,Week 2,Learn In Team

    我觉得做为一个团队,每个人的能力固然重要,但是更重要的是几个人能同心协力. 俗话说“三个臭皮匠,赛过诸葛亮”,团队合作往往能激发出团体不可思议的潜力,集体协作干出的成果往往能超过成员个人业绩的总和.在 ...

  5. Daily Scrumming 2015.10.22(Day 3)

    今明两天任务表 Member Today’s Task Tomorrow’s Task 江昊 学习rails ActiveRecord 购买.注册域名 继续学习rails ActiveRecord 数 ...

  6. [BUAA OO]第四次博客作业

      一.      测试与正确性论证的区别 在最后一个单元的OO作业中,我们主要进行了代码的测试与正确性论证工作.这俩者在作业中的体现分别是junit单元测试以及jsf论述语言.这两者在java代码开 ...

  7. t团队项目计划

    团队的backlog: .用户登录网站后,可以选择是买或者卖, (1)买 点击链接,可以分类浏览商品信息,也可以按价钱筛选 (2)卖 点击链接,选择要挂出的商品种类,填写信息(名称.价格.数量等)接着 ...

  8. 读书笔记 之 java编程思想3

    现在已经读到第二章  ,这个发现好多已经能都知道了  但是还是有自己比较生疏的比如说就是 储存到什么地方:书中介绍五种储存的地方 分别为1储存器,2堆栈,3堆4常量储存 5非RAM储存,java的出来 ...

  9. 求int型数组和最大子数组 续

    之前的博文里已经实现过该程序的构思.编译.运行,本次就不再重复与之相雷同的内容. 题目:与别人借组,借助求int型数组最大和子数组的问题,考虑大数溢出和int取值范围的问题 要求: 调试程序  当子数 ...

  10. visualStudo编译c程序, 提示函数unSafe问题

    问题描述: 在利用visualStudo进行C语言编程时,若C语言源程序中有print,freopen等函数时,IDE软件总是unSafe,而且无法通过编译. 解决方案: 在<视图>中找到 ...