路径寻找问题 UVA 1499 - Gem And Prince

Nowadays princess Claire wants one more guard and posts the ads throughout the kingdom. For her unparalleled beauty, generality, goodness and other virtues, many people gather at the capital and apply for the position. Because princess Claire is very clever, she doesn't want a fool to be her guard. As Claire is clever, she invents a game to test the applicants. The game is described as follows.

The game begins with a rectangular board of n rows and m columns, containing n * m grids. Each grid is filled with a gem and each gem is covered by one color, denoted by a number.(as the following shows).

\epsfbox{p5722a.eps}

\epsfbox{p5722b.eps}

\epsfbox{p5722c.eps}

\epsfbox{p5722d.eps}

If a gem has the same color with another one, and shares the same corner or the same border with it, the two are considered to be adjacent. Two adjacent gems are said to be connective. And we define that if A and B are connective, B and C are connective, then A and C are connective, namely the adjacency is transitive. Each time we can choose a gem and pick up all of the gems connected to it, including itself, and get a score equal to the square of the number of the gems we pick this time(but to make the game more challenging, the number of gems to be picked each time must be equal or larger than three).Another rule is that if one gem is picked, all the gems above it(if there is any)fall down to fill its grid,and if there is one column containing no gems at all, all the columns at its right(also if there is any) move left to fill the column. These rules can be shown as follows.


1 1 3      0 0 3      0 0 0      0 0 0
1 2 1   -> 0 2 0   -> 0 0 3   -> 0 3 0
1 1 2      0 0 2      0 2 2      2 2 0
 [a]        [b]        [c]        [d]


As the picture [a] above,all the gems that has color 1 are connective. After we choose one of them to be picked, all the gems that are connected to it must also be picked together, as the picture [b] shows (here we use 0 to denote the holes generated by the absence of gems).

Then the rest gems fall, as shown in picture [c]. Then the rest gems move left, as shown in picture [d]. Because we picked six gems at this time, our score increases 6 * 6 = 36. And furthermore, because we cannot find another gem, which has at least three gems connected to it(including itself),to be picked, the game comes to an end.

Each applicant will face such a board and the one who gets the highest score will have the honor to serve princess Claire.

Aswmtjdsj also wants to serve for princess Claire. But he realizes that competing with so many people, even among whom there are powerful ACMers, apparently there is little chance to succeed. With the strong desire to be the lucky dog, Aswmtjdsj asks you for help.

Can you help make his dream come true?

Input 

There are no more than 15 test cases, separated by a blank line, end with EOF. Each case has n + 1 lines, the first line of a case has three integers n, m, k (1$ \le$n, m$ \le$8, 1$ \le$k$ \le$6). Each of the next n lines contains m integers. The integer at (i + 1)th line and jth column denotes the color of the gem at the grid (i, j), where the grid(1, 1) denotes the top left one, while the grid(n, m) is the lower right one. The integer in the grid is among [1, k].

Output 

For each case you should output the highest score you can get in one single line.

Sample Input 

3 3 3
1 1 3
1 2 1
1 1 2

5 4 3
2 2 3 3
1 1 3 3
3 2 2 2
3 1 1 1
3 1 2 2

Sample Output 

36
103

题意:这个没什么好解释的啦,规则没有难懂的地方。


思路:我直接dfs的,当然也可以写成宽搜的形式啦。我的状态里面用string保存了一个序列用于判重的。然后状态转移没有问题的话,就没有什么问题的了。写的时候可以把各个功能分开写,思路会清晰一点的。想那个降落用一个函数写,然后往左靠也用一个函数写。在写个输出状态的用于debug。


代码:

#include<iostream>
#include<cstdio>
#include<string.h>
#include<cstring>
#include<string>
#include<vector>
#include<queue>
#include<ctime>
#include<map>
using namespace std;
int ans , n , m , k;
map<string,int> d;

inline int getx(int r,int c) { return r*m+c; }
inline int row(int x) { return x/m; }
inline int col(int x) { return x%m; }
int Move[2][8] = { {-1,-1,0,1,1,1,0,-1},{0,1,1,1,0,-1,-1,-1}};

inline bool inRange(int r,int c) 
{
	return 0<=r&&r<n&&0<=c&&c<m;
}

struct State
{
	State() { 
		memset(board,0,sizeof(board)); 
		memset(cnt,0,sizeof(cnt)); 
		score = 0; 
		str = "";
	}
	int board[8][8];
	string str;
	int cnt[7];
	int score;
	int max_score() {
		int sum = 0;
		for (int i = 1 ; i <= k ; ++i) sum += cnt[i]*cnt[i];
		return sum;
	}
	bool bfs(State & st,int r,int c , bool vis[70]) const {
		queue<int> q;
		int x = getx(r,c);
		q.push(x);
		int type = st.board[r][c];
		vis[x] = true;
		int ret = 0;
		while (q.size()) {
			++ret;
			x = q.front(); q.pop();
			int r = row(x) , c = col(x);
			st.board[r][c] = 0;
			st.str[getx(r,c)] = '0';
			for (int i = 0 ; i < 8 ; ++i) {
				int rr = r+Move[0][i];
				int cc = c+Move[1][i];
				if (!inRange(rr,cc) || vis[getx(rr,cc)]) continue;
				if (st.board[rr][cc]!=type) continue;
				q.push(getx(rr,cc));
				vis[getx(rr,cc)] = true;
			}
		}
		if (ret <= 2) return false;
		st.score += ret*ret;
		st.cnt[type] -= ret;
		return true;
	}

	void fall() {
		for (int r = n-2 ; r >= 0 ; --r) {
			for (int c = 0 ;  c < m ; ++c) {
				if (!board[r][c]) continue;
				int q = r;
				while (inRange(q+1,c) && board[q+1][c]==0) ++q;
				if (q==r) continue;
				board[q][c] = board[r][c];
				str[getx(q,c)] = str[getx(r,c)];
				str[getx(r,c)] = '0';
				board[r][c] = 0;
			}
		}
	}

	void left() {
		for (int c = 1 ; c < m ; ++c) if (board[n-1][c]) {
			int q = c;
			while (inRange(n-1,q-1) && !board[n-1][q-1]) --q;
			if (q==c) continue;
			for (int r = 0 ; r < n ; ++r) { 
				board[r][q] = board[r][c]; 
				str[getx(r,q)] = str[getx(r,c)];
				str[getx(r,c)] = '0';
				board[r][c] = 0;
			}
		}
	}

	void output() {
		printf("\n");
		for (int i = 0 ; i < n ; ++i)
		{
			for (int j = 0 ; j < m ; ++j) printf("%d",board[i][j]);
			printf("\n");
		}
		printf("\n");
	}

	void expand(vector<State>&s) const {
		bool vis[70];
		memset(vis,0,sizeof(vis));
		for (int i = 0 ; i < n ; ++i) 
		{
			for (int j = 0 ; j < m ; ++j) if (!vis[getx(i,j)]) {
				if (board[i][j]==0) continue;
				State now = *this;
				if (!bfs(now,i,j,vis)) continue;
				now.fall();
				now.left();
				s.push_back(now);
			}
		}
	}
};

void dfs(int score,State & s)
{
	if (d.count(s.str) && d[s.str] >= score) 
		return;
	if (score + s.max_score() <= ans) return;
	d[s.str] = score;
//	s.output();
	vector<State> next;
	s.expand(next);
	if (next.empty()) {
		ans = max(ans,score);
		return;
	}
	for (int i = 0 ; i < next.size() ; ++i) 
		dfs(next[i].score,next[i]);
}

void GetInput() {
	n = 8 , m = 8 , k = 6;
	int T = 10;
	freopen("input.in","w",stdout);
	while (T--) {
		printf("%d % d% d\n",n,m,k);
		for (int i = 0 ; i < n ; ++i)
		{
			for (int j = 0 ; j < m ; ++j) printf("%d ",rand()%k+1);
			printf("\n");
		}
		printf("\n");
	}
}

int main() 
{
	//GetInput(); return 0;
//	freopen("input.in","r",stdin);
//	clock_t s = clock();
	while (scanf("%d%d%d",&n,&m,&k)==3)
	{
		State start;
		for (int r = 0 ; r < n ; ++r)
		{
			for (int c = 0 ; c < m ; ++c)
			{
				int x; scanf("%d",&x);
				start.board[r][c] = x;
				start.str += x+'0';
				++start.cnt[x];
			}
		}
		ans = 0;
		d.clear();
		dfs(0,start);
		printf("%d\n",ans);
		//printf("node: %d  Ans:%d\n",d.size(),ans);
	}
	//clock_t finish = clock();
	//printf("Time: %dms\n",finish-s);
/* node: 4052  Ans:440
	node: 2408  Ans:466
	node: 1624  Ans:197
	node: 2223  Ans:305
	node: 6524  Ans:316
	node: 1461  Ans:437
	node: 543  Ans:384
	node: 9226  Ans:389
	node: 1825  Ans:585
	node: 2256  Ans:457
	Time: 18488ms
*/
	//Time: 21127ms
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值