@description@

在一块平原上有一头大象。

平原被分成 n×m 个格子。初始时大象位于 (1,1)。每一秒,大象会移动到一个相邻的格子上(四连通),但不会移动到平原外面。由于你视力不好,你无法知道大象每次移动到哪个格子上。

你可以使用火球术来攻击地面。每次释放火球术,你可以攻击任意多个格子。每个格子只能被攻击一次。大象不能移动到被攻击过的格子上,如果大象相邻的格子都无法移动,那么它会停在原地不动。

你的目标是最后只剩下一个格子没有被火球术攻击过,然后你去那里活捉大象。在此之前,你必须保证你的火球术不会击中大象。由于大象的战斗力十分强大,只有在某些格子中你才能抓住大象。

然而,由于你魔法水平不高,在使用火球术前你需要进行蓄势。第一次蓄势的时间至少为 n+m 秒,接下来每次蓄势时间都要比上次长。蓄势时间必须是整数秒。你希望最小化最后一次的蓄势时间。

注意:每一秒大象先移动,接着你才会释放火球术。也就是说,如果你第一次的蓄势时间为 n+m 秒,那么大象已经移动了 n+m 次。

input

第一行包含两个整数 n, m。n, m ≤ 1000。

接下来 n 行每行 m 个数,每个数只能是 0 或 1。第 i+1 行第 j 列的数表示在 (i,j) 这个格子中,你能否抓住大象(1 表示能,0 表示不能)。

output

输出若干行,每行表示释放一次火球术。

每行第一个整数表示蓄势时间,接下来若干个整数表示攻击的格子,第 i 行第 j 列的格子编号为 (i−1)∗m + j。每行最后输出一个 0。

如果无解输出一行一个整数 −1。

sample input

3 3

1 1 1

1 1 1

1 1 1

sample output

7 1 3 7 9 0

9 2 4 6 8 0

@solution@

大象太强了。

将矩形黑白染色,标记 (1, 1) 为白,则某时刻大象要么在黑格要么在白格。

不妨假设大象在白格,则只能删除黑格,且要保证删完过后剩下的白格仍然连通才合法。删剩下最后一个格子则结束。

我们可以将这个删格子的过程倒过来,从某一个格子开始往外添加同色格子,并且保持连通。于是就可以得到每一时刻我们需要删去格子的编号。

如果我们蓄势时间为偶数,则大象的位置黑白颜色不变;否则位置变为相反的颜色。

通过我们所知道的第一次删去格子的颜色,以及大象的初始位置在 (1, 1) 即白格,可以确定第一次是奇数蓄势还是偶数蓄势。

假如经过一定次数的删格子后,大象在某种颜色的格子。则可以得到上一次一定是删异色的格子,则这一次应该删与大象所在格同色的格子,需要大象离开。

所以得到:除了第一次蓄势时间奇偶性需要判断一下,剩下的蓄势时间一定为奇数。

可以发现对于某一个点而言,第一次删去的肯定包括矩形四个角落的某一个。于是我们可以对于这个点到四个角落的曼哈顿距离求最大值,并判断第一次的奇偶性与 (m+n) 的奇偶性是否相同,就可以推出以这个点为终末状态的答案是多少。

将所有的合法点都求解对应的答案,并取最小值。输出方案不难,按照加格子的思路来思考即可,或者也可以按照每一个点到终点的曼哈顿距离来思考。

复杂度 O(nm)。

@accepted code@

#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
const int MAXN = 1000;
int n, m, x, y, cnt = 0;
int fun(int x, int y) {
return max(max(x-1 + y-1, n-x + m-y), max(x-1 + m-y, n-x + y-1));
}
int abs(int x) {return x > 0 ? x : -x;}
vector<int>ans[2*MAXN + 5];
int X[MAXN*MAXN + 5], Y[MAXN*MAXN + 5];
int main() {
scanf("%d%d", &n, &m), x = -1, y = -1;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++) {
int a; scanf("%d", &a);
if( a ) {
if( x == -1 && y == -1 )
x = i, y = j;
else if( fun(x, y) > fun(i, j) )
x = i, y = j;
else if( fun(x, y) == fun(i, j) ) {
if( ( (((x + y)&1) ^ (fun(x, y)&1)) == ((n + m)&1) ) && ( (((i + j)&1) ^ (fun(i, j)&1)) != ((n + m)&1) ) )
x = i, y = j;
}
}
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
ans[abs(i-x)+abs(j-y)].push_back(++cnt), X[cnt] = i, Y[cnt] = j;
int p = n + m; bool flag = true;
for(int i=n+m;i>=1;i--) {
if( ans[i].empty() ) continue;
if( flag ) {
p += ((X[ans[i][0]]-1+Y[ans[i][0]]-1)&1)^((n+m)&1)^1, flag = false;
printf("%d", p);
if( p % 2 == 0 ) p--;
}
else {
p += 2;
printf("%d", p);
}
for(int j=0;j<ans[i].size();j++)
printf(" %d", ans[i][j]);
printf(" %d\n", 0);
}
}

@details@

啊啊虽然题解不难理解,代码也不是很难写,但是通过反过来加格子的角度来思考问题这个真的想不到啊。。。

考场上只写了个 50 分的构造方法。。。

@noi - 172@ 追捕大象的更多相关文章

  1. 【QQ技术】群文件报毒怎样下载?~ 变相绕过QQ复杂检验过程

    刚才又人问我,要是群文件被鉴定为病毒那怎么下载? 我简单说一下吧: 其实qq客户端过滤比较严的,而web段却还是老一套,很多人说出现这个情况其实是腾讯已经把他库里面的文件删了,其实不然 如果源删了,那 ...

  2. 【FINAL】NOI

    我就是复习一下..根本就不是什么题解...谁也看不懂的... NOI2007 社交网络         最短路 货币兑换         斜率优化动态规划 项链工厂         线段树 生成树计数 ...

  3. hadoop意外之旅--巧合遇到一只大象

    公司面临转型,所有开发也难免面临转型,开始选择自己想要走的方向进行研究. 说来也巧合,最近正好说搭个hadoop环境玩玩,结果遇到转型还被选为大数据小组组长.(尴尬) 开始一场遇到大象之旅,希望能在这 ...

  4. 从一道NOI练习题说递推和递归

    一.递推: 所谓递推,简单理解就是推导数列的通项公式.先举一个简单的例子(另一个NOI练习题,但不是这次要解的问题): 楼梯有n(100 > n > 0)阶台阶,上楼时可以一步上1阶,也可 ...

  5. NOI 动态规划题集

    noi 1996 登山 noi 8780 拦截导弹 noi 4977 怪盗基德的滑翔翼 noi 6045 开餐馆 noi 2718 移动路线 noi 2728 摘花生 noi 2985 数字组合 no ...

  6. noi 6047 分蛋糕

    题目链接:http://noi.openjudge.cn/ch0405/6047/ 和Uva1629很类似,不过,可能用记忆化难写一点,状态初始化懒得搞了.就用循环好了. 状态描叙也可以修改,那个题目 ...

  7. [python实现设计模式]-2.模板方法模式---把大象关进冰箱.

    平时大家上班都很累,为了增加工作中的欢乐气氛,黄页组准备搞个游戏. 游戏的名字是把大象关进冰箱.游戏很简单,需要把指定的物品放进冰箱. 我们都知道,把大象放进冰箱,分3步. 第一步,打开冰箱门,第二步 ...

  8. 洛谷P1371 NOI元丹

    P1371 NOI元丹 71通过 394提交 题目提供者洛谷OnlineJudge 标签云端评测 难度普及/提高- 提交  讨论  题解 最新讨论 我觉得不需要讨论O long long 不够 没有取 ...

  9. leetcode 172

    172. Factorial Trailing Zeroes Given an integer n, return the number of trailing zeroes in n!. Note: ...

随机推荐

  1. python基--re模块的使用

    正则表达式: 正则表达式本身是一种小型的.高度专业化的编程语言,然而在python中,通过内嵌集成re模块让调用者们可以直接调用来实现正则匹配.正则表达模式被变异成一系列的字节码,然后由C语言编写的 ...

  2. 2019.8.7 NOIP模拟测试14 反思总结

    先扔代码 调完自闭网络流了,新一轮考试前看看能不能赶完…… 考得极其爆炸,心态也极其爆炸,真的是认识到自己能力上的不足 思维跑偏,代码能力差 就这样吧,再努力努力,不行就AFO T1旋转子段: 因为我 ...

  3. vue里图片压缩上传组件

    //单图上传 <template> <div> <div class="uploader" v-if='!dwimg'> <van-upl ...

  4. LUOGU P2921 [USACO08DEC]在农场万圣节Trick or Treat on the Farm

    传送门 解题思路 记忆化搜索,如果搜到环,就将环的大小处理出来. 代码 #include<iostream> #include<cstdio> #include<cstr ...

  5. 解决IE6、IE7、Firefox兼容最简单的CSS Hack

    写三句代码来控制一个属性,区别Firefox,IE7,IE6: background:orange; *background:green !important; *background:blue;   ...

  6. OWIN启动类检测

    每个OWIN应用程序都有一个启动类,可以在这个类里为应用程序管道指定组件.有不同的方式可以将启动类与运行时关联起来,这依赖于选择的托管模型(OwinHost,IIS,IIS-Express).本教程中 ...

  7. 在n个球中,任意取出m个(不放回),求共有多少种取法

    要求: 在n个球中,任意取出m个(不放回),求共有多少种取法 分析: 假设3个球A,B,C,任意取出2个,可分为取出的球中含A的部分和不含A的部分.即AB,AC为一组,BC为一组. 设函数F(n,m) ...

  8. Leetcode720.Longest Word in Dictionary词典中最长的单词

    给出一个字符串数组words组成的一本英语词典.从中找出最长的一个单词,该单词是由words词典中其他单词逐步添加一个字母组成.若其中有多个可行的答案,则返回答案中字典序最小的单词. 若无答案,则返回 ...

  9. 日期格式之——new Date()的用法

    获取时间: 1 var myDate = new Date();//获取系统当前时间 获取特定格式的时间: 1 myDate.getYear(); //获取当前年份(2位) 2 myDate.getF ...

  10. cocos2dX 之CCAnimation/CCAnimate

    我们今天来学习cocos2dX里面的动画的制作, 有人说, 不是前面CCAction已经学过了吗? 怎么还要学, CCAction是动作, 而我们今天要学的是动画哦, 是让一个东西动起来哦, 好了进入 ...