转载请说明出处: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;
}
}
}