题目链接: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

 #include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std; typedef long long LL;
const int maxn = + ; LL board[maxn][maxn];
LL d1[maxn<<], d2[maxn<<];
pair<int, int> ans[];
LL tmp[]; inline LL read() // 这个读入是避免TLE的关键
{
int x = , f = ;
char ch = getchar();
while (ch >= '' && ch <= '')
{
x = *x + ch-'';
ch = getchar();
}
return (LL)(x * f);
} int main()
{
int n, x1, x2, y1, y2;
while (scanf("%d", &n) != EOF)
{
memset(d1, , sizeof(d1));
memset(d2, , sizeof(d2));
getchar(); // 不能省!n之后有个空格= =
for (int i = ; i <= n; i++)
{
for (int j = ; j <= n; j++)
{
board[i][j] = read();
d1[i+j] += board[i][j];
d2[i-j+n] += board[i][j];
}
}
tmp[] = tmp[] = -; // 0也可以,但是后面要>=,防止多次被替换还是-1好,省时一点吧
for (int i = ; i <= n; i++)
{
for (int j = ; j <= n; j++)
{
LL val = d1[i+j] + d2[i-j+n] - board[i][j];
if (val > tmp[(i+j)&])
{
tmp[(i+j)&] = val;
ans[(i+j)&].first = i;
ans[(i+j)&].second = j;
}
}
}
printf("%lld\n", tmp[] + tmp[]);
printf("%d %d %d %d\n", ans[].first, ans[].second, ans[].first, ans[].second);
}
return ;
}

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

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

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

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

真是又长又耗时啊~~

Time:  1122ms     Memory:  125504KB

 #include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std; typedef long long LL;
const int maxn = + ; struct node
{
LL s;
int x, y;
bool operator < (const node& a) const
{
return s < a.s;
}
}num[maxn*maxn]; LL board[maxn][maxn];
LL sum[maxn][maxn]; inline LL read() // 这个读入是避免TLE的关键
{
int x = , f = ;
char ch = getchar();
while (ch >= '' && ch <= '')
{
x = *x + ch-'';
ch = getchar();
}
return (LL)(x * f);
} int main()
{
int n;
while (scanf("%d", &n) != EOF)
{
getchar();
for (int i = ; i <= n; i++)
{
for (int j = ; j <= n; j++)
board[i][j] = (LL)read();
}
memset(sum, , sizeof(sum));
// 第 1 行
int i = ;
for (int j = ; j <= n; j++)
{
LL ss = ;
int ti = i;
int tj = j; // 右下
while (ti <= n && tj <= n)
{
ss += board[ti][tj];
ti++;
tj++;
}
ti = i;
tj = j;
while (ti <= n && tj <= n)
{
sum[ti][tj] += ss;
ti++;
tj++;
}
ti = i;
tj = j; // 左下
ss = ;
while (ti <= n && tj >= )
{
ss += board[ti][tj];
ti++;
tj--;
}
ti = i;
tj = j;
while (ti <= n && tj >= )
{
sum[ti][tj] += ss;
ti++;
tj--;
}
}
// 第 1 列
int j = ;
for (int i = ; i <= n; i++)
{
LL ss = ;
int ti = i;
int tj = j;
while (ti <= n && tj <= n)
{
ss += board[ti][tj];
ti++;
tj++;
} ti = i;
tj = j;
while (ti <= n && tj <= n)
{
sum[ti][tj] += ss;
ti++;
tj++;
}
}
j = n;
for (int i = ; i <= n; i++)
{
LL ss = ;
int ti = i;
int tj = j;
while (ti <= n && tj >= )
{
ss += board[ti][tj];
ti++;
tj--;
}
ti = i;
tj = j;
while (ti <= n && tj >= )
{
sum[ti][tj] += ss;
ti++;
tj--;
}
}
int cnt = ;
for (int i = ; i <= n; i++)
{
for (int j = ; j <= n; j++)
{
num[cnt].x = i;
num[cnt].y = j;
num[cnt++].s = sum[i][j] - board[i][j];
}
}
int flag = ;
LL maxsum;
int x1, y1, x2, y2;
sort(num, num+cnt);
for (int i = cnt-; i >= && !flag; i--)
{
for (int j = i-; j >= && !flag; j--)
{
int t1 = num[i].x + num[i].y;
int t2 = abs(num[j].x - num[j].y);
if ((t1 + t2) % == )
continue;
if (abs(num[i].x-num[j].x) != abs(num[i].y - num[j].y))
{
flag = ;
x1 = num[i].x, x2 = num[j].x;
y1 = num[i].y, y2 = num[j].y;
maxsum = num[i].s + num[j].s;
break;
}
}
}
printf("%lld\n", maxsum);
printf("%d %d %d %d\n", x1, y1, x2, y2);
}
return ;
}

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. Java爬取51job保存到MySQL并进行分析

    大二下实训课结业作业,想着就爬个工作信息,原本是要用python的,后面想想就用java试试看, java就自学了一个月左右,想要锻炼一下自己面向对象的思想等等的, 然后网上转了一圈,拉钩什么的是动态 ...

  2. Android动画系列 - PropertyAnim 详解

    前言:上一篇文章传统View动画与Property动画基础及比较简单对Android动画系统的基础做了介绍,本篇文章将对PropertyAnimation进行全面深入的探讨,本篇文章可以分为两大块,从 ...

  3. GridView数据绑定控件的模版列时设置显示的格式

    形式 语法 结果 数字 {0:N2} 12.36   数字 {0:N0} 13   货币 {0:c2} $12.36   货币 {0:c4} $12.3656   货币 "¥{0:N2}&q ...

  4. Hive UDF开发-简介

    Hive进行UDF开发十分简单,此处所说UDF为Temporary的function,所以需要hive版本在0.4.0以上才可以. Hive的UDF开发只需要重构UDF类的evaluate函数即可.例 ...

  5. 基于ACCESS和ASP的SQL多个表查询与计算统计代码(一)

    近期在写几个关于"Project - Subitem - Task"的管理系统,说是系统还是有点夸大了,基本就是一个多表查询调用和insert.update的数据库操作.仅仅是出现 ...

  6. 使用Cout输出String和CString对象

    CString和string都是一个类,不同的是CString主要用于MFC或者是ATL编程中,而string则多用于Windows控制台编程中 在实际编程过程中,我们经常用到string或者是CSt ...

  7. 第14章8节《MonkeyRunner源代码剖析》 HierarchyViewer实现原理-获取控件列表并建立控件树

    在上几节的描写叙述中,我们把HierarchyViewer初始化好.也把ViewServer给装备好了.那如今距离获得一个控件去操作它是万事具备仅仅欠东风了,欠了那一股春风了?欠了的是建立控件树这个东 ...

  8. (八):构建WineLib DLL

    (一):介绍 出于某些原因,你可能会发现你想要和使用Windows DLL一样使用你的Linux库.对于这有一些原因例如以下: 你正在支持一个使用多个第三方库的大应用.该项目在Linux中是可用的,可 ...

  9. 【php】在Windows2003下配置Apache2.4与php5.4

    直接配置php一直使用如同<[php]本地开发环境的部署与helloworld>(点击打开链接)的一键傻瓜包,被批为极度不专业,关键是这些一键傻瓜包LAMP的版本号不好控制.port什么的 ...

  10. Mataplotlib绘图和可视化

    Mataplotlib是一个强大的python绘图和数据可视化工具包 安装方法:pip install matplotlib 引用方法:import matplotlib.pyplot as plt ...