USACO Starry Night 解题报告

USER: chen chen [thestor1]
TASK: starry
LANG: C++

Compiling...
Compile: OK

Executing...
   Test 1: TEST OK [0.008 secs, 3508 KB]
   Test 2: TEST OK [0.008 secs, 3508 KB]
   Test 3: TEST OK [0.011 secs, 3508 KB]
   Test 4: TEST OK [0.008 secs, 3508 KB]
   Test 5: TEST OK [0.016 secs, 3508 KB]

All tests OK.

Your program ('starry') produced all correct answers! This is your submission #3 for this problem. Congratulations!


这道题我是用的是最直接的方法。用DFS得到每个cluster,然后之前所有的cluster都逐一比较。比较的时候也是8种形状逐一比较。当然,先比较star的个数是否一样,轮廓(长方形)是否一样。每个cluster还用一个set保存了里面所有的点。如果usaco支持unordered_set的话,说不定会更快些。标准答案比较的时候看着像是位操作啥的,应该比我的直观解法快特别多,也没看懂。

/* 
ID: thestor1 
LANG: C++ 
TASK: starry 
*/
#include <iostream>
#include <fstream>  
#include <cmath>  
#include <cstdio>  
#include <cstring>  
#include <climits>  
#include <cassert>  
#include <string>  
#include <vector>  
#include <set>
#include <map>  
#include <queue>  
#include <stack>  
#include <algorithm>
// #include <unordered_map>
// #include <unordered_set>

using namespace std;

const int MAXW = 100;

class Cluster {
public:
	char label;
	int H, W;
	int ll, lr, ul, ur;
	int size;
	// std::vector<pair<int, int> > ones;
	set<int> ones;

	Cluster()
	{
		H = W = ll = lr = ul = ur = -1;
		size = 0;
	}
};

bool isIn(int r, int c, int H, int W)
{
	return 0 <= r && r < H && 0 <= c && c < W;
}

inline int index(int r, int c)
{
	return r * MAXW + c;
}

void dfs(int r, int c, int H, int W, vector<std::vector<char> > &skymap, Cluster &cluster)
{
	if (cluster.ll < 0 || r < cluster.ll)
	{
		cluster.ll = r;
	}
	if (cluster.lr < 0 || c < cluster.lr)
	{
		cluster.lr = c;
	}
	if (r > cluster.ul)
	{
		cluster.ul = r;
	}
	if (c > cluster.ur)
	{
		cluster.ur = c;
	}

	skymap[r][c] = cluster.label;
	cluster.size++;
	// cluster.ones.push_back(make_pair(r, c));
	cluster.ones.insert(index(r, c));

	int dx[] = {-1, -1, -1, 0, 1, 1, 1, 0}, dy[] = {-1, 0, 1, 1, 1, 0, -1, -1};
	for (int d = 0; d < 8; ++d)
	{
		int nr = r + dx[d], nc = c + dy[d];
		if (isIn(nr, nc, H, W) && skymap[nr][nc] == '1')
		{
			dfs(nr, nc, H, W, skymap, cluster);
		}
	}
}

bool isSame(const Cluster &c1, Cluster &c2, vector<std::vector<char> > &skymap)
{
	if (c1.size != c2.size)
	{
		return false;
	}
	
	if (c1.H == c2.H && c1.W == c2.W)
	{
		// up->down, left->right
		bool flag = true;
		
		for (int i1 = c1.ll, i2 = c2.ll; i1 <= c1.ul && i2 <= c2.ul; ++i1, ++i2)
		{
			for (int j1 = c1.lr, j2 = c2.lr; j1 <= c1.ur && j2 <= c2.ur; ++j1, ++j2)
			{
				if (c1.ones.count(index(i1, j1)) != c2.ones.count(index(i2, j2)))
				{
					flag = false;
					break;
				}
			}
			if (!flag)
			{
				break;
			}
		}

		if (flag)
		{
			return true;
		}

		// up->down, right->left
		flag = true;
		for (int i1 = c1.ll, i2 = c2.ll; i1 <= c1.ul && i2 <= c2.ul; ++i1, ++i2)
		{
			for (int j1 = c1.lr, j2 = c2.ur; j1 <= c1.ur && j2 >= c2.lr; ++j1, --j2)
			{
				if (c1.ones.count(index(i1, j1)) != c2.ones.count(index(i2, j2)))
				{
					flag = false;
					break;
				}
			}
			if (!flag)
			{
				break;
			}
		}

		if (flag)
		{
			return true;
		}

		// down->up, left->right
		flag = true;

		for (int i1 = c1.ll, i2 = c2.ul; i1 <= c1.ul && i2 >= c2.ll; ++i1, --i2)
		{
			for (int j1 = c1.lr, j2 = c2.lr; j1 <= c1.ur && j2 <= c2.ur; ++j1, ++j2)
			{
				if (c1.ones.count(index(i1, j1)) != c2.ones.count(index(i2, j2)))
				{
					flag = false;
					break;
				}
			}
			if (!flag)
			{
				break;
			}
		}

		if (flag)
		{
			return true;
		}

		// down->up, right->left
		flag = true;
		for (int i1 = c1.ll, i2 = c2.ul; i1 <= c1.ul && i2 >= c2.ll; ++i1, --i2)
		{
			for (int j1 = c1.lr, j2 = c2.ur; j1 <= c1.ur && j2 >= c2.lr; ++j1, --j2)
			{
				if (c1.ones.count(index(i1, j1)) != c2.ones.count(index(i2, j2)))
				{
					flag = false;
					break;
				}
			}
			if (!flag)
			{
				break;
			}
		}

		if (flag)
		{
			return true;
		}
	}

	if (c1.H == c2.W && c1.W == c2.H)
	{
		// left->right, down->up
		bool flag = true;

		for (int i1 = c1.ll, j2 = c2.lr; i1 <= c1.ul && j2 <= c2.ur; ++i1, ++j2)
		{
			for (int j1 = c1.lr, i2 = c2.ul; j1 <= c1.ur && i2 >= c2.ll; ++j1, --i2)
			{
				if (c1.ones.count(index(i1, j1)) != c2.ones.count(index(i2, j2)))
				{
					flag = false;
					break;
				}
			}
			if (!flag)
			{
				break;
			}
		}

		if (flag)
		{
			return true;
		}

		// right->left, down->up
		flag = true;

		for (int i1 = c1.ll, j2 = c2.ur; i1 <= c1.ul && j2 >= c2.lr; ++i1, --j2)
		{
			for (int j1 = c1.lr, i2 = c2.ul; j1 <= c1.ur && i2 >= c2.ll; ++j1, --i2)
			{
				if (c1.ones.count(index(i1, j1)) != c2.ones.count(index(i2, j2)))
				{
					flag = false;
					break;
				}
			}
			if (!flag)
			{
				break;
			}
		}

		if (flag)
		{
			return true;
		}

		// left->right, up->down
		flag = true;

		for (int i1 = c1.ll, j2 = c2.lr; i1 <= c1.ul && j2 <= c2.ur; ++i1, ++j2)
		{
			for (int j1 = c1.lr, i2 = c2.ll; j1 <= c1.ur && i2 <= c2.ul; ++j1, ++i2)
			{
				if (c1.ones.count(index(i1, j1)) != c2.ones.count(index(i2, j2)))
				{
					flag = false;
					break;
				}
			}
			if (!flag)
			{
				break;
			}
		}

		if (flag)
		{
			return true;
		}

		// right->left, up->down
		flag = true;

		for (int i1 = c1.ll, j2 = c2.ur; i1 <= c1.ul && j2 >= c2.lr; ++i1, --j2)
		{
			for (int j1 = c1.lr, i2 = c2.ll; j1 <= c1.ur && i2 <= c2.ul; ++j1, ++i2)
			{
				if (c1.ones.count(index(i1, j1)) != c2.ones.count(index(i2, j2)))
				{
					flag = false;
					break;
				}
			}
			if (!flag)
			{
				break;
			}
		}

		if (flag)
		{
			return true;
		}
	}

	return false;
}

void repaint(vector<std::vector<char> > &skymap, char label, Cluster &cluster)
{
	for (int r = cluster.ll; r <= cluster.ul; ++r)
	{
		for (int c = cluster.lr; c <= cluster.ur; ++c)
		{
			if (skymap[r][c] == label)
			{
				skymap[r][c] = cluster.label;
			}
		}
	}
}

int main()
{
	ifstream fin("starry.in");
	ofstream fout("starry.out");

	int W, H;
	fin>>W>>H;
	std::vector<std::vector<char> > skymap(H, std::vector<char>(W, '0'));
	std::vector<Cluster> clusters;
	for (int r = 0; r < H; ++r)
	{
		string row;
		fin>>row;
		for (int c = 0; c < W; ++c)
		{
			if (row[c] == '1')
			{
				skymap[r][c] = '1';
			}
		}
	}

	char label = 'a';
	for (int r = 0; r < H; ++r)
	{
		for (int c = 0; c < W; ++c)
		{
			if (skymap[r][c] == '1')
			{
				Cluster cluster;
				cluster.label = label;
				dfs(r, c, H, W, skymap, cluster);
				// sort(cluster.ones.begin(), cluster.ones.end());
				cluster.H = cluster.ul - cluster.ll + 1;
				cluster.W = cluster.ur - cluster.lr + 1;

				bool unique = true;
				for (int i = 0; i < clusters.size(); ++i)
				{
					if (isSame(clusters[i], cluster, skymap))
					{
						unique = false;
						cluster.label = clusters[i].label;
						repaint(skymap, label, cluster);
						break;
					}
				}

				if (unique)
				{
					// cluster.label = label;
					clusters.push_back(cluster);
					// paint(skymap, cluster);
					label++;
				}
			}
		}
	}

	for (int r = 0; r < H; ++r)
	{
		for (int c = 0; c < W; ++c)
		{
			fout<<skymap[r][c];
		}
		fout<<endl;
	}

	fin.close();
	fout.close();
	return 0;  
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值