Entertaining Geodetics

我的未来我决定 提交于 2020-02-27 19:46:34

题目虽然是要求是按螺旋的更改地板的颜色 但是即使是按螺旋的方式更改那么也是地图中所有的地板的颜色都会改变 可以将有什么颜色的地板的数量都记录下来然后算更改的次数的时候只要加上要更改的地板的数量并把刚才更改的那一种颜色的地板数量加到符号颜色的地板的数量上 并把刚才的数量清空
也就是求入队的顺序的问题了
在这里插入图片描述
首先先比较层数的大小 层数大的肯定放在层数小的后面 即绿色的放在 红色的后面
接下来就是同一层的比较了 首先是全在最左边一列的时候那么就只要比较一下x坐标就行了 如果一个在最左列 一个在其他的列那么肯定是最左列的放在后面
同理比较一下最上面的一行
然后就是右边一列 和最下面一行的情况 也是差不多的。

/*
问题描述
  在此游戏中地图被分为了许多叫作Geo格的正方形方格,其中一些被涂上色,假设没有涂色的为透明色。
  地图中还有些Geo符号,它们样子像不同颜色的金字塔(包括透明Geo符号)。每个Geo符号都坐落在Geo格上,每个Geo格上最多一个Geo符号。
  Geo符号可以被消除。为了更好地理解Geo符号在消除时发生了什么,这里引入把刚消除的Geo符号放入的队列。
  从队列中取出Geo符号,观察包含Geo符号的Geo格的颜色,如果它不是透明的且颜色不同于Geo符号,则把所有这个颜色的Geo格重新涂为Geo符号的颜色(透明的Geo符号则为透明色)。重涂色是在一个无限大的区域从那个有符号的Geo格子开始螺旋状进行的。
  .
  换句话说,我们选择所有需要重涂色的方格找到它们在以有符号格为中心的无限螺旋表格中所对应的数字。此后按数字的增加顺序我们对其重染色。
  如果在重染色时遇到一个格子包含另一个Geo符号的情况则将Geo符号移出并放置在队列尾部。
  当重染色结束后Geo符号彻底消失,并且队列中下一个Geo符号(如果有)将取出,重复此操作直至队列为空。
  为了更好地理解请看一个例子。
  你知道所有格子的颜色、所有符号的位置。计算出队列里符号彻底消失时所造成的重染色次数。
  推荐使用I64d输出。
输入格式
  第一行包含两个数n,m(1<=n,m<=300)—地图的高和宽。
  接下来n行每行m个数—格子的颜色。
  接下来n行每行m个数—对符号的描述,-1表示没有符号,否则数字代表符号的颜色。
  所有颜色都是属于0到10^9的整数,0表示透明。
  最后一行两个数x,y(1<=x<=n,1<=y<=m)—需要消除的Geo符号的行和列位置。行从上到下标记,列从左往右标记,从1开始。保证位置(x,y)包含一个符号。
输出格式
  一行一个数—符号消除时重染色次数。
样例输入
5 5
9 0 1 1 0
0 0 3 2 0
1 1 1 3 0
1 1 1 3 0
0 1 2 0 3
-1 1 -1 3 -1
-1 -1 -1 0 -1
-1 -1 -1 -1 -1
-1 2 3 -1 -1
-1 -1 -1 -1 2
4 2
样例输出
35
*/
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<map>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
typedef struct{
	int x,y;
}zb_t; 				//创建一个结构体 里面放的是  x 和 y 坐标 
zb_t now;			//队列头的那一个符号的 x y 坐标 
int max(int,int);
bool cmp(const zb_t&,const zb_t&);
int main(void)
{
	map<int,int>colorbh;     //将题目中的颜色转换成自己定义的颜色的编号 方便将地板是同一个颜色的符号的下标记录到同一个vector的数组中 
	int hs,ls,colorcnt = 0,i,j;//行数 列数  自己定义的颜色的编号 
	static vector <zb_t>jl[300*300+1];// 存放 地板是同一个颜色的符号的下标
	colorbh[0] = colorcnt++;			//将0 号放入 自己定义的颜色编号为 0 
	scanf("%d%d",&hs,&ls);
	static int di[300][300],fh[300][300];//di[i][j] 用来存放 i , j的地板的颜色  fh 是符号 
	static long long nur_di[300*300];	//nur_di[i]	用来存放颜色为 i 的 地板有多少个 
	memset(nur_di,0,sizeof(nur_di));
	for(i = 0;i < hs;i++)
	{
		for(j = 0;j < ls;j++)
		{
			scanf("%d",di[i]+j);
			if(!colorbh.count(di[i][j])) //如果输入数据的这个颜色没有放入这个 map中 
			{								//那么就给这个颜色定义编号为  colorcnt 
				colorbh[di[i][j]] = colorcnt++;
			}
			di[i][j] = colorbh[di[i][j]];//并将 di 里面改成自己定义的颜色编号 
			nur_di[di[i][j]]++;			// nur_di[i]	用来存放颜色为 i 的 地板有多少个
		}
	}
	for(i = 0;i < hs;i++)
	{
		for(j = 0;j < ls;j++)
		{
			scanf("%d",fh[i]+j);
			if(fh[i][j] != -1)
			{
				if(!colorbh.count(fh[i][j]))//符号也是一样的 
				{
					colorbh[fh[i][j]] = colorcnt++;
				}
				fh[i][j] = colorbh[fh[i][j]];
			}
		}
	}
	int x,y,t = 0,w = 0;
	scanf("%d%d",&x,&y);
	x--;y--;
	for(i = 0;i < hs;i++)
	{
		for(j = 0;j < ls;j++)
		{
			if(fh[i][j] != -1)
			{
				if(!(i == x && j == y))
				{
					zb_t t;
					t.x = i;t.y = j;
					jl[di[i][j]].push_back(t);  // 存放 地板是同一个颜色的符号的下标
				}
				
			}
		}
	}
	zb_t dui[hs*ls];  //定义一个队列  
	dui[w].x = x;dui[w++].y = y;//将  x y  入队 
	int cnow = di[x][y],cchg;//cnow  是当前要改变的地板的颜色的编号  cchg 是当前符号的颜色的编号
	long long ans = 0;
	while(t < w)
	{
		now = dui[t];t++;	//出队 
		i = now.x;j = now.y;
		cchg = fh[i][j];
		if(cnow == 0 || cnow == fh[i][j])
		{
			continue;
		}
		nur_di[cchg]+=nur_di[cnow];//更改当前的符号颜色的地板拥有的数量 
		ans += nur_di[cnow];		//答案加上现在要改变颜色的地板数量 
		nur_di[cnow] = 0;			//颜色改完之后变成零 
		sort(jl[cnow].begin(),jl[cnow].end(),cmp);//排一下序 下面就号理解了 
		int k;
		for(k = 0;k < jl[cnow].size();k++)
		{
			dui[w++] = jl[cnow][k];
		}
		jl[cnow].clear();
		cnow = cchg;
	}
	printf("%lld\n",ans);
	return 0;
}
int max(int a,int b)
{
	return a > b ? a:b;
}

bool cmp(const zb_t&u,const zb_t&v)
{
	int djc1 = max(abs(u.x-now.x),abs(u.y-now.y)),djc2 = max(abs(v.x-now.x),abs(v.y-now.y));
	if(djc1 != djc2)
	{
		return djc1 < djc2;
	}
	int min_x = now.x-djc1,min_y = now.y-djc1+1;
	if(u.y == min_y-1 && v.y == min_y-1)
	{
		return u.x > v.x;
	}
	if(u.y == min_y-1 || v.y == min_y-1)
	{
		return !(u.y == min_y-1);
	}
	if(u.x == min_x && v.x == min_x)
	{
		return u.y < v.y;
	}
	if(u.x == min_x || v.x == min_x)
	{
		return u.x == min_x;
	}
	if(u.x != v.x)
	{
		return u.x < v.x;
	}
	return u.y > v.y;
}

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!