ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

洛谷P2749 [USACO5.1]夜空繁星Starry Night

2021-03-05 23:01:37  阅读:185  来源: 互联网

标签:连通 洛谷 temp int P2749 rep tempcnt Night include


零、洛谷链接

一、简要题意

给你一张图,要找出所有八连通的连通块,规定不管旋转翻转后,只要相同的两个连通块算为同一种连通块。

对相同连通块染相同一个小写字母,按字典序输出染色后的图。

下面八个全为同一种连通块。

二、解法 + code

我们可以看出,本题最大的难点在于如何判断相似。

根据小学玄学知识&样例,我们有一些发现:

两个相似的图,从同一个点到别的点的直线距离(曼哈顿距离)相等。

来张图:

但是,我们在走连通块时,由于旋转和翻转的关系,并不能保障任意选择两点就是同一个点。

一看数据范围:\(n≤100\)

因此,可以将所有的点到其他点的曼哈顿距离都算出来,再加在一块求和,以这个数值作为比较相似的因素即可。

似乎是解决了?

快乐地把代码写出来♪:

// 仅放核心代码:
int main()
{
	scanf("%d%d", &m, &n);
	rep(i, 1, n)
	{
		rep(j, 1, m)
		{
			cin >> mapp[i][j];
		}
	}
	rep(i, 1, n)
	{
		rep(j, 1, m)
		{
			if(mapp[i][j] == '1')
			{
				tempcnt = 0;
				long long tempsum = 0;
				bfs(i, j); 
				rep(k, 1, tempcnt)
				{
					rep(l, 1, tempcnt)
					{
						tempsum += sqrt(abs(temp[k].x - temp[l].x) * abs(temp[k].x - temp[l].x) + abs(temp[k].y - temp[l].y) * abs(temp[k].y - temp[l].y));
					}
			//	cout << tempsum  << endl;
				}
			//	cout << "tempcnt:" << tempcnt << endl;
				int f = 0; 
				rep(k, 1, cnt)
				{
			
					if(tempsum == hhash[k])
					{
						f = 1;
						color(i, j, k); 
						break;
					} 
				}
				if(!f)
				{
					hhash[++cnt] = tempsum; 
				//	cout << cnt << endl;
					color(i, j, cnt);
				}
			}
		}
	}
	rep(i, 1, n)
	{
		rep(j, 1, m)
		{
			printf("%c", mapp[i][j]);
		}
		printf("\n");
	}
	return 0;
}

结果:

干得漂亮,有60分了

我们再来思考:因为曼哈顿距离带了根号,而这个代码里面全部取整了,所以两个仅有一点差别的图就会挂掉。、

所以带个double试试?

// by pjx Feb.
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <queue>
#include <stack>
#define REP(i, x, y) for(register int i = x; i < y; i++)
#define rep(i, x, y) for(register int i = x; i <= y; i++)
#define PER(i, x, y) for(register int i = x; i > y; i--)
#define per(i, x, y) for(register int i = x; i >= y; i--)
using namespace std;
const int N = 605; 
int n, m, tempcnt;
char mapp[N][N];
double hhash[N], tempsum;
int cnt;
int dx[] = {0, -1, -1, -1, 0, 0, 1, 1, 1};//八个方向 
int dy[] = {0, -1, 0, 1, -1, 1, -1, 0, 1};
queue <int> qx, qy;
struct node{//用来存连通块每个点的坐标 
	int x, y;
}temp[N * N];
void bfs(int x, int y)//搜索连通块 
{
	temp[++tempcnt].x = x;
	temp[tempcnt].y = y;
	qx.push(x);
	qy.push(y);
	mapp[x][y] = '2';//如果搜到了一个点,那把它标记为未染色过但搜索过 
	while(!qx.empty())
	{
		int tx = qx.front();
		int ty = qy.front();
		qx.pop();
		qy.pop();
		rep(i, 1, 8)
		{
			int xx = tx + dx[i];
			int yy = ty + dy[i];
			if(xx >= 1 && xx <= n && yy >= 1 && yy <= m && mapp[xx][yy] == '1')
			{
				mapp[xx][yy] = '2';
				qx.push(xx);
				qy.push(yy);
				temp[++tempcnt].x = xx;
				temp[tempcnt].y = yy;				 
			}
		}
	}
}
void color(int x, int y, int word)//给这个图重新染色 
{
	qx.push(x);
	qy.push(y);
	mapp[x][y] = char(word + 'a' - 1);
	while(!qx.empty())
	{
		int tx = qx.front();
		int ty = qy.front();
		qx.pop();
		qy.pop();
		rep(i, 1, 8)
		{
			int xx = tx + dx[i];
			int yy = ty + dy[i];
			if(xx >= 1 && xx <= n && yy >= 1 && yy <= m && mapp[xx][yy] == '2')
			{
				mapp[xx][yy] = char(word + 'a' - 1);
				qx.push(xx);
				qy.push(yy);				 
			}
		}
	}
}
bool check()//判断两个连通块是否为同一种 
{
    tempsum = 0.0000;
    for(int k = 1; k <= tempcnt; k++)
	{
	    for(int l = 1; l <= tempcnt; l++)
		{
			tempsum += sqrt(double(abs(temp[k].x - temp[l].x)) * double(abs(temp[k].x - temp[l].x)) + double(abs(temp[k].y - temp[l].y)) * double(abs(temp[k].y - temp[l].y)));
			//因为带根号,为了更加精确,保留4位小数 
		}
	}
	for(int k = 1; k <= cnt; k++)
	{
		if(abs(tempsum - hhash[k]) <= 0.0001)//如果以前找到过与其总和一样的,就表明是第k种连通块 
		{
		    return 1;
		} 
	}
	return 0; 

}
int main()
{
	scanf("%d%d", &m, &n);
	rep(i, 1, n)
	{
		rep(j, 1, m)
		{
			cin >> mapp[i][j];
		}
	}
	rep(i, 1, n)
	{
		rep(j, 1, m)
		{
			if(mapp[i][j] == '1')
			{
				tempcnt = 0;
				bfs(i, j); 
                if(check())
                {
                   	for(int k = 1; k <= cnt; k++)
					{
						if(abs(tempsum - hhash[k]) <= 0.0001)//如果以前找到过与其总和一样的,就表明是第k种连通块 
						{
						    color(i, j, k);//染第k种颜色 
						    break;
						} 
					} 
                }
            	else//否则,增加新的一种,染新的一种颜色 
            	{
            	    hhash[++cnt] = double(tempsum); 
	              	color(i, j, cnt);
	           }
			}
		}
	}
	rep(i, 1, n)
	{
		rep(j, 1, m)
		{
			printf("%c", mapp[i][j]);
		}
		printf("\n");
	}
	return 0;
}

nice过了

标签:连通,洛谷,temp,int,P2749,rep,tempcnt,Night,include
来源: https://www.cnblogs.com/pjxpjx/p/14488943.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有