CF 366E - Dima and Magic Guitar 最远曼哈顿距离

题目:http://codeforces.com/problemset/problem/366/E

事实上就是找 n * m 矩阵中数字 x 和 数字 y 的最远距离。

方法參照武森的论文《浅谈信息学中的“0”和“1”》

先约定符号:xi,xj  (i,j)是x的下标,当然。矩阵中的值是能够反复的

上面是武森的论文原文。加上我之前的符号约定,我在做点解释:

事实上那个max={四种可能}  更好的写法是:

|xi-yi|+|xj-yj|=max((1),(2),(3),(4))

(1)(xi+xj)-(yi+yj)   就是3-3  最大就是max3-min3

(2)(xi-xj)-(yi-yj)      2-2  最大就是max2-min2

(3)(-xi+xj)-(-yi+yj)  1-1  最大就是max1-min1

(4)(-xi-xj)-(-yi-yj)    0-0  最大就是max0-min0

那么维护数组num[v][4][2]    num[v][4][0]   就是0 1 2 3 情况下的最小值。num[v][4][1]   就是0 1 2 3 情况下的最大值。由于v能够出如今矩阵的多个位置就是说矩阵能够有反复值。所以维护的[0] [1]可能不是一个坐标处的,可是也是能够的

这么解释应该都能理解,然后假设是多维。只是是维护num[v][8][2]----剩下的。你懂得~~~

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <iostream>
#include <iomanip>
#include <cmath>
#include <map>
#include <set>
#include <queue>
using namespace std;

#define ls(rt) rt*2
#define rs(rt) rt*2+1
#define ll long long
#define ull unsigned long long
#define rep(i,s,e) for(int i=s;i<e;i++)
#define repe(i,s,e) for(int i=s;i<=e;i++)
#define CL(a,b) memset(a,b,sizeof(a))
#define IN(s) freopen(s,"r",stdin)
#define OUT(s) freopen(s,"w",stdout)
const ll ll_INF = ((ull)(-1))>>1;
const int INF = 100000000;
const double EPS = 1e-8;

int ABS(int x)
{
    return x>=0?x:(-x);
}

int a[10][4][2];
int n,m,k,s;

int main()
{
    //IN("in.txt");
    int x,y;
    while(~scanf("%d%d%d%d",&n,&m,&k,&s))
    {
        for(int i=0;i<10;i++)
            for(int j=0;j<4;j++)
            {
                a[i][j][0]=INF;//0  min
                a[i][j][1]=-INF;//1 max
            }
        //printf("cap\n");
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++)
            {
                scanf("%d",&x);
                a[x][0][0]=min(a[x][0][0],-i-j);
                a[x][0][1]=max(a[x][0][1],-i-j);
                a[x][1][0]=min(a[x][1][0],-i+j);
                a[x][1][1]=max(a[x][1][1],-i+j);
                a[x][2][0]=min(a[x][2][0],i-j);
                a[x][2][1]=max(a[x][2][1],i-j);
                a[x][3][0]=min(a[x][3][0],i+j);
                a[x][3][1]=max(a[x][3][1],i+j);
            }
        int ans=0;
        scanf("%d",&x);
        for(int i=1;i<s;i++)
        {
            scanf("%d",&y);
            for(int j=0;j<4;j++)
            {
                 ans=max(ans,ABS(a[x][j][1]-a[y][j][0]));
                 ans=max(ans,ABS(a[x][j][0]-a[y][j][1]));
            }
            x=y;
        }
        printf("%d\n",ans);
    }
    return 0;
}

还看到还有一种做法也是不错的:http://vawait.com/codeforces-366e/

事实上道理一样

(1)(xi+xj)-(yi+yj)=xi+xj+(-yi-yj)   就是3+0  最大就是max3+max0

(2)(xi-xj)+(-yi+yj)      2+1  最大就是max2+max1

(3)(-xi+xj)+(yi-yj)  1+2  最大就是max1+max2

(4)(-xi-xj)+(yi+yj)    0+3  最大就是max0+max3

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<string>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<stack>
using namespace std;
#define rep(i, a, b) for (int i = (a); i <= (b); ++i)
#define red(i, a, b) for (int i = (a); i >= (b); --i)
#define clr( x , y ) memset(x,y,sizeof(x))
#define sqr(x) ((x) * (x))
typedef long long lint;
int n,m,k,s,x,y,a[10][5];

void init()
{
    scanf("%d%d%d%d",&n,&m,&k,&s);
    clr(a,243);
    rep(i,1,n)
        rep(j,1,m) {
            scanf("%d",&x);
            a[x][0] = max( a[x][0] , -i - j );
            a[x][1] = max( a[x][1] , -i + j );
            a[x][2] = max( a[x][2] , i - j );
            a[x][3] = max( a[x][3] , i + j );
        }
}

void work()
{
    int ans = -100000000;
    scanf("%d",&x);
    rep(i,2,s) {
        scanf("%d",&y);
        rep(j,0,3) ans = max( ans , a[x][j] + a[y][3-j] );
        x = y;
    }
    cout<<ans;
}

int main()
{
    init();
    work();
    return 0;
}
时间: 2024-10-09 10:22:54

CF 366E - Dima and Magic Guitar 最远曼哈顿距离的相关文章

Dima and Magic Guitar CodeForces - 366E

Dima and Magic Guitar CodeForces - 366E 题意: http://blog.csdn.net/u011026968/article/details/38716425http://vawait.com/2013/11/codeforces-366e/http://www.cnblogs.com/jianglangcaijin/archive/2013/11/25/3441319.html 对于s中任意相邻两个数x和y,都要求在矩形中找出任意两个分别等于x和y的点

Codeforces 491B. New York Hotel 最远曼哈顿距离

最远曼哈顿距离有两个性质: 1: 对每个点(x,y)  分别计算  +x+y , -x+y , x-y , -x-y 然后统计每种组合的最大值就可以了, 不会对结果产生影响 2: 去掉绝对值 , 设正号为0负号为1 则 两个点的符号是可以通过异或的得到的. 如两个点 P(x,y) 和 Q(a,b) 若去掉绝对值符号后P的两个坐标为 -x +y 既对应数字 10  那么Q对应的数字则为 01 既 +a -b 两个点的曼哈顿距离为 -x +y +a -b B. New York Hotel time

最远 Manhattan 距离

最远 Manhattan 距离 处理问题 K维空间下的n个点,求两点最远曼哈顿距离 思路 以二维为例介绍算法思想,即可类推到k维.对于P,Q两点,曼哈顿距离|Px-Qx|+|Py-Qy|可看作(±Px±Py)-(±Qx±Qy),不难发现Px应该与Qx的符号相同,Py与Qy符号相同,因此共四种情况.这样写的好处是,每个点可以表示成相同的形式(±Px±Py).而曼哈顿距离一定是四种情况中值最大的那种,所以要求两点最远曼哈顿距离,可以枚举所有的取符号情况,对于每种情况,维护出上述表示下n个点的最大值与

CF 366C Dima and Salad [天平DP]

题目大意:n个水果,水果有甜度和卡路里两个属性,选择一些水果,使得甜度之和与卡路里之和比例为k,并且使得甜度之和最大 我们可以定义二维dp,dp[当前游标扫到的个数][平衡度]=当前平衡度下最大的ai和,平衡度定义为ai-bi*k,很巧秒的定义方式,可以节省一维时空. 注意到平衡度可正可负(范围在-10000到10000) 我们可以定义如下 int m[1111][22222] int *d[i]=&m[i][10000] dp[num+1][balance]=max(self,dp[num][

CF 711B - Chris and Magic Square

挺简单的一道题,但是做的时候没想好就开始写代码了,导致迷之WA,还是要多练习啊. #include <iostream> #include <cstdio> #include <algorithm> #include <queue> #include <set> #define LL long long int using namespace std; LL Map[505][505]; int main() { cin.sync_with_st

CF 272E Dima and Horses 染色,dfs 难度:2

http://codeforces.com/problemset/problem/272/E 把仇恨关系想象为边, 因为度只能为0,1,2,3,所以有以下几种 0,1 直接放即可 2: 有(1,1),(0,2)两种情况,第一种随便放,第二种放0那里 3:有(1,2),(0,3)两种情况,第一种放1,第二种放0那里 也就是说,怎样都有解 dfs寻找即可 不过一开始觉得这样不靠谱,因为时间复杂度很高,不过没想到过了 #include <cstdio> #include <vector>

bzoj3382[Usaco2004 Open]Cave Cows 3 洞穴里的牛之三*

bzoj3382[Usaco2004 Open]Cave Cows 3 洞穴里的牛之三 题意: n个点,求最远曼哈顿距离.n≤50000. 题解: 曼哈顿距离转切比雪夫距离(点(x,y)变为点(x+y,x-y)),然后输出最大横坐标-最小横坐标与最大纵坐标-最小纵坐标的较大值即可. 代码: 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #define inc(i,j,k) for(in

cf Round 613

A.Peter and Snow Blower(计算几何) 给定一个点和一个多边形,求出这个多边形绕这个点旋转一圈后形成的面积.保证这个点不在多边形内. 画个图能明白 这个图形是一个圆环,那么就是这个点距离多边形边缘最远的距离形成的圆面积减去这个点距离多边形边缘最近的距离形成的圆面积.我们可以得出距离最远的点一定是多边形的顶点.而距离最近的点不一定是多边形的顶点,但是在多边形的边上.我们用勾股定理判断点与每条边形成的三角形的两边角.如果有一个边角是钝角,则表示距离最近的点是顶点.如果都是锐角,则

树上某点距离最远的结点

题目链接 题目需要得到树上每个结点出发可到达的最远的结点,顺便求出树的直径. 这里顺便总结一下求解的两种方法. 第一种思路:三种dfs(bfs) 第一遍dfs(bfs)从任意结点出发,找到距离该结点最远的结点u(直径的端点之一). 第二遍dfs(bfs)从u出发,求出其他点到u的距离,最长的即为v(直径的另一个端点). 第三遍dfs(bfs)从v出发,求出其他点到v的距离. 可以知道,对于任意结点x,其在树上可到达的最远的距离为max{dist[x][u], dist[x][v]}. 故其最大值