CF 366E - Dima and Magic Guitar 最远曼哈顿距离
2014-08-21 00:08
453 查看
题目: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
其实就是找 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; }
相关文章推荐
- CF 366E Dima and Magic Guitar(最远哈密顿距离)
- CF 366E - Dima and Magic Guitar 最远曼哈顿距离
- cf E. Dima and Magic Guitar
- Codeforces 366E Dima and Magic Guitar 暴力
- HDU 5626 Clarke and points 平面两点曼哈顿最远距离
- CodeForces 366 E. Dima and Magic Guitar
- cf-Round #214 (Div. 2)-D-Dima and Trap Graph-dfs+二分
- HDU 4666 Hyperspace (最远曼哈顿距离)
- cf C. Dima and Salad
- cf 167.div2 E.Dima and Horses
- poj 2926 Requirements 【5维点集最远曼哈顿距离】
- POJ-2926 Requirements 最远曼哈顿距离
- cf-366C-Dima and Salad
- poj 2926:Requirements(最远曼哈顿距离,入门题)
- cf C. Dima and Containers
- POJ 2926 Requirements (空间最远曼哈顿距离)
- hdoj 4666 Hyperspace 【最远曼哈顿距离】
- CF round167 Div1 C Dima and Horses
- cf-381A-Sereja and Dima
- hdu 4666 Hyperspace(多维度最远曼哈顿距离)