传教士问题

转载请说明出处:http://blog.csdn.net/u013797947

本题的思路是使传教士们所占用的传教区域重叠,即找出每个传教士的对角线上还没被占用的点的数目最少。

代码如下:

//From Big Heart
//传教士
#include <iostream>
using namespace std;
int find_min(int i,int j);
void change(int i,int j);
int a[20][20];
int n,m;	//4行3列
int main(){
	int min_ = 400,i_=21,j_=21,timer = 0;
	memset(a,0,sizeof(a));
	cin >> n >> m;
	bool isContinue = false;
	do{
	isContinue = false;
	for(int i=0;i<m;i++)
		for(int j=0;j<n;j++){
			if(a[i][j] == 0){
				isContinue = true;
				int temp = find_min(i,j);
				if(min_>temp){
					min_ = temp;
					i_=i,j_=j;
				}
			}
		}
		change(i_,j_);
		timer++;
		min_ = 400;
	}while(isContinue);
	cout<<--timer;
}
int find_min(int i,int j){    //找出不为-1的点所对应对角线上点数的最小值
	int count = 0,x,y;
	int x_[4] = {1,1,-1,-1},y_[4] = {1,-1,-1,1};
	for(int timer = 0;timer<4;timer++){
		x=i,y=j;
		for(;x>=0&&x<m&&y>=0&&y<n;x+=x_[timer],y+=y_[timer]){
			if(a[x][y] == 0){
				count++;
			}
		}
	}
	return count-3;
}
void change(int i,int j){  	//使对角线上的值都变为 -1
	int x_[4] = {1,1,-1,-1},y_[4] = {1,-1,-1,1},x,y;
	for(int timer = 0;timer<4;timer++){
		x=i,y=j;
		for(;x>=0&&x<m&&y>=0&&y<n;x+=x_[timer],y+=y_[timer]){
			if(a[x][y] == 0)
			a[x][y] = -1;
		}
	}
	
}
点赞