题目链接:http://codeforces.com/contest/463/problem/C

题目意思:要在一个 n * n 大小的棋盘上放置两个bishop,bishop可以攻击的所有位置是包括经过bishop 位置的两条成90度的对角线所经过的所有坐标点。每个坐标点都有数字在上面,放置一个bishop后,可以获得能被放置的bishop攻击的所有坐标点的数字的和。但是有一个条件限制:同一个坐标点不能被两个bishop攻击,也就是四条对角线的交点不能是棋盘上的某个坐标点。求出在该条件限制下,两个bishop的放置位置以及能获得的最大和。

首先没有看到这个条件wa了很多次: place two bishops on the chessboard in such a way that there is no cell that is attacked by both of them。

好不容易看到之后,就各种TLE了,原来是读入问题!!!!涨姿势勒= =

可喜的是,原来自己最开始的做法是可取的,不过都是因为读入问题。

先介绍作者的灵活高效版:

先看一个图:

作者的做法有两个巧妙之处:

(1)求 bishop 能够攻击的所有坐标点的和,简而言之就是一个坐标点的两条对角线的和。

  设两个数组d1[],d2[],用于保存两种方向下的对角线总和。(虚线部分标明了方向)。d1[]数组是通过d1[i+j] += board[i][j] 来算的,而 d2是这样:d2[i-j+n] += board[i][j]。

如果要求某个特定的坐标(i, j)的对角线和,那么就是d1[i+j] + d2[i-j+n] - board[i][j] ,之所以要减去board是因为每个坐标点的和都被重复算多了一次。

(2)判断攻击的方法

假设 bishop1 坐标为(i1, j1),bishop2 为(i2, j2),如果( i1 + j1),( i2 + j2) 同奇或同偶,那么就存在某一个坐标点同时被两个bishop 攻击!

所以要满足不存在某个坐标同时被两个bishop 攻击,就需要(i1 + j1) 和 (i2+j2) 处于一奇一偶的情况。那么奇数找一个最大值,偶数的话又找一个最大值,加起来就是两个bishop放置后能够获得的最大和了。

Time:  217ms     Memory:  31400KB

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cstring>
  5. using namespace std;
  6.  
  7. typedef long long LL;
  8. const int maxn = + ;
  9.  
  10. LL board[maxn][maxn];
  11. LL d1[maxn<<], d2[maxn<<];
  12. pair<int, int> ans[];
  13. LL tmp[];
  14.  
  15. inline LL read() // 这个读入是避免TLE的关键
  16. {
  17. int x = , f = ;
  18. char ch = getchar();
  19. while (ch >= '' && ch <= '')
  20. {
  21. x = *x + ch-'';
  22. ch = getchar();
  23. }
  24. return (LL)(x * f);
  25. }
  26.  
  27. int main()
  28. {
  29. int n, x1, x2, y1, y2;
  30. while (scanf("%d", &n) != EOF)
  31. {
  32. memset(d1, , sizeof(d1));
  33. memset(d2, , sizeof(d2));
  34. getchar(); // 不能省!n之后有个空格= =
  35. for (int i = ; i <= n; i++)
  36. {
  37. for (int j = ; j <= n; j++)
  38. {
  39. board[i][j] = read();
  40. d1[i+j] += board[i][j];
  41. d2[i-j+n] += board[i][j];
  42. }
  43. }
  44. tmp[] = tmp[] = -; // 0也可以,但是后面要>=,防止多次被替换还是-1好,省时一点吧
  45. for (int i = ; i <= n; i++)
  46. {
  47. for (int j = ; j <= n; j++)
  48. {
  49. LL val = d1[i+j] + d2[i-j+n] - board[i][j];
  50. if (val > tmp[(i+j)&])
  51. {
  52. tmp[(i+j)&] = val;
  53. ans[(i+j)&].first = i;
  54. ans[(i+j)&].second = j;
  55. }
  56. }
  57. }
  58. printf("%lld\n", tmp[] + tmp[]);
  59. printf("%d %d %d %d\n", ans[].first, ans[].second, ans[].first, ans[].second);
  60. }
  61. return ;
  62. }

接下来就是我的做法(大家可以忽略)

求对角线的和的时候,我是采取从第1行,第1列,最后1列出发来求得的,最后还是需要减去board[i][j],代码量好大,因为太多重复 = =

至于判断攻击,除了利用abs函数(恰好对角线),还利用了之前做的一条 cf370A 的 Rook, Bishop  and King的做法啦—— 判断Bishop 步数。

毕竟自己写的,留下纪念吧 = =

真是又长又耗时啊~~

Time:  1122ms     Memory:  125504KB

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cstring>
  5. #include <cmath>
  6. #include <algorithm>
  7. using namespace std;
  8.  
  9. typedef long long LL;
  10. const int maxn = + ;
  11.  
  12. struct node
  13. {
  14. LL s;
  15. int x, y;
  16. bool operator < (const node& a) const
  17. {
  18. return s < a.s;
  19. }
  20. }num[maxn*maxn];
  21.  
  22. LL board[maxn][maxn];
  23. LL sum[maxn][maxn];
  24.  
  25. inline LL read() // 这个读入是避免TLE的关键
  26. {
  27. int x = , f = ;
  28. char ch = getchar();
  29. while (ch >= '' && ch <= '')
  30. {
  31. x = *x + ch-'';
  32. ch = getchar();
  33. }
  34. return (LL)(x * f);
  35. }
  36.  
  37. int main()
  38. {
  39. int n;
  40. while (scanf("%d", &n) != EOF)
  41. {
  42. getchar();
  43. for (int i = ; i <= n; i++)
  44. {
  45. for (int j = ; j <= n; j++)
  46. board[i][j] = (LL)read();
  47. }
  48. memset(sum, , sizeof(sum));
  49. // 第 1 行
  50. int i = ;
  51. for (int j = ; j <= n; j++)
  52. {
  53. LL ss = ;
  54. int ti = i;
  55. int tj = j; // 右下
  56. while (ti <= n && tj <= n)
  57. {
  58. ss += board[ti][tj];
  59. ti++;
  60. tj++;
  61. }
  62. ti = i;
  63. tj = j;
  64. while (ti <= n && tj <= n)
  65. {
  66. sum[ti][tj] += ss;
  67. ti++;
  68. tj++;
  69. }
  70. ti = i;
  71. tj = j; // 左下
  72. ss = ;
  73. while (ti <= n && tj >= )
  74. {
  75. ss += board[ti][tj];
  76. ti++;
  77. tj--;
  78. }
  79. ti = i;
  80. tj = j;
  81. while (ti <= n && tj >= )
  82. {
  83. sum[ti][tj] += ss;
  84. ti++;
  85. tj--;
  86. }
  87. }
  88. // 第 1 列
  89. int j = ;
  90. for (int i = ; i <= n; i++)
  91. {
  92. LL ss = ;
  93. int ti = i;
  94. int tj = j;
  95. while (ti <= n && tj <= n)
  96. {
  97. ss += board[ti][tj];
  98. ti++;
  99. tj++;
  100. }
  101.  
  102. ti = i;
  103. tj = j;
  104. while (ti <= n && tj <= n)
  105. {
  106. sum[ti][tj] += ss;
  107. ti++;
  108. tj++;
  109. }
  110. }
  111. j = n;
  112. for (int i = ; i <= n; i++)
  113. {
  114. LL ss = ;
  115. int ti = i;
  116. int tj = j;
  117. while (ti <= n && tj >= )
  118. {
  119. ss += board[ti][tj];
  120. ti++;
  121. tj--;
  122. }
  123. ti = i;
  124. tj = j;
  125. while (ti <= n && tj >= )
  126. {
  127. sum[ti][tj] += ss;
  128. ti++;
  129. tj--;
  130. }
  131. }
  132. int cnt = ;
  133. for (int i = ; i <= n; i++)
  134. {
  135. for (int j = ; j <= n; j++)
  136. {
  137. num[cnt].x = i;
  138. num[cnt].y = j;
  139. num[cnt++].s = sum[i][j] - board[i][j];
  140. }
  141. }
  142. int flag = ;
  143. LL maxsum;
  144. int x1, y1, x2, y2;
  145. sort(num, num+cnt);
  146. for (int i = cnt-; i >= && !flag; i--)
  147. {
  148. for (int j = i-; j >= && !flag; j--)
  149. {
  150. int t1 = num[i].x + num[i].y;
  151. int t2 = abs(num[j].x - num[j].y);
  152. if ((t1 + t2) % == )
  153. continue;
  154. if (abs(num[i].x-num[j].x) != abs(num[i].y - num[j].y))
  155. {
  156. flag = ;
  157. x1 = num[i].x, x2 = num[j].x;
  158. y1 = num[i].y, y2 = num[j].y;
  159. maxsum = num[i].s + num[j].s;
  160. break;
  161. }
  162. }
  163. }
  164. printf("%lld\n", maxsum);
  165. printf("%d %d %d %d\n", x1, y1, x2, y2);
  166. }
  167. return ;
  168. }

codeforces 463C. Gargari and Bishops 解题报告的更多相关文章

  1. Codeforces 463C Gargari and Bishops 题解

    题目出处: http://codeforces.com/contest/463/problem/C 感觉本题还是挺难的.须要好好总结一下. 计算对角线的公式: 1 右斜对角线,也叫主对角线的下标计算公 ...

  2. codeforces 463C Gargari and Bishops

    题目链接 这个题, 最主要的应该是找到对角线上的格子的关系. “ \" 这种对角线, 关系是x-y+n相等, ” / “ 这种, 关系是x+y相等.知道每个格子的两种对角线的值, 那么这个格 ...

  3. Codeforces Educational Round 92 赛后解题报告(A-G)

    Codeforces Educational Round 92 赛后解题报告 惨 huayucaiji 惨 A. LCM Problem 赛前:A题嘛,总归简单的咯 赛后:A题这种**题居然想了20m ...

  4. codeforces 476C.Dreamoon and Sums 解题报告

    题目链接:http://codeforces.com/problemset/problem/476/C 题目意思:给出两个数:a 和 b,要求算出 (x/b) / (x%b) == k,其中 k 的取 ...

  5. Codeforces Round #382 (Div. 2) 解题报告

    CF一如既往在深夜举行,我也一如既往在周三上午的C++课上进行了virtual participation.这次div2的题目除了E题都水的一塌糊涂,参赛时的E题最后也没有几个参赛者AC,排名又成为了 ...

  6. codeforces 507B. Amr and Pins 解题报告

    题目链接:http://codeforces.com/problemset/problem/507/B 题目意思:给出圆的半径,以及圆心坐标和最终圆心要到达的坐标位置.问最少步数是多少.移动见下图.( ...

  7. codeforces 500B.New Year Permutation 解题报告

    题目链接:http://codeforces.com/problemset/problem/500/B 题目意思:给出一个含有 n 个数的排列:p1, p2, ..., pn-1, pn.紧接着是一个 ...

  8. codeforces B. Xenia and Ringroad 解题报告

    题目链接:http://codeforces.com/problemset/problem/339/B 题目理解不难,这句是解题的关键 In order to complete the i-th ta ...

  9. codeforces 462C Appleman and Toastman 解题报告

    题目链接:http://codeforces.com/problemset/problem/461/A 题目意思:给出一群由 n 个数组成的集合你,依次循环执行两种操作: (1)每次Toastman得 ...

随机推荐

  1. 提高速度 history 的利用

    history的介绍history是shell的内置命令,其内容在系统默认的shell的man手册中.history是显示在终端输入并执行的过命令,系统默认保留1000条.[root@localhos ...

  2. Java多线程中Lock的使用

    Jdk1.5以后,在java.util.concurrent.locks包下,有一组实现线程同步的接口和类,说到线程的同步,可能大家都会想到synchronized关键字, 这是java内置的关键字, ...

  3. Android中使用SDcard进行文件的读取

    来自:http://www.cnblogs.com/greatverve/archive/2012/01/13/android-SDcard.html 平时我们需要在手机上面存储想音频,视频等等的大文 ...

  4. Android 学习之路和App开发框架

    学习之路: 1. http://www.stormzhang.com/android/2014/07/07/learn-android-from-rookie/ 框架: 2. https://gith ...

  5. android清除缓存为什么总是存在12k?

    转载请注明出处:http://blog.csdn.net/droyon/article/details/41116529 android手机在4.2之后.清除缓存总是会残留12k的大小.预计强迫症患者 ...

  6. [Hibernate开发之路](3)基础配置

    一 JDBC链接 通常你希望SessionFactory来为你创建和缓存(pool)JDBC连接. 假设你採用这样的方式, 仅仅须要例如以下例所看到的那样,打开一个Session: Session s ...

  7. Nginx简单了解

    1.静态HTTP服务器 首先,Nginx是一个HTTP服务器,可以将服务器上的静态文件(如HTML.图片)通过HTTP协议展现给客户端. 配置: server { listen80; # 端口号 lo ...

  8. Android开发之裁切(拍照+相冊)图像并设置头像小结

    先看效果:                                       watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5 ...

  9. STL源代码剖析——基本算法stl_algobase.h

    前言 在STL中.算法是常常被使用的,算法在整个STL中起到很关键的数据.本节介绍的是一些基本算法,包括equal.fill.fill_n,iter_swap.lexicographical_comp ...

  10. JS计算网页停留时间

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/ ...