Fire Net
Time Limit : 2000/1000ms (Java/Other) Memory Limit : 65536/32768K (Java/Other)
Total Submission(s) : 10 Accepted Submission(s) : 3
Font: Times New Roman | Verdana | Georgia
Font Size: ← →
Problem Description
A blockhouse is a small castle that has four openings through which to shoot. The four openings are facing North, East, South, and West, respectively. There will be one machine gun shooting through each opening.
Here we assume that a bullet is so powerful that it can run across any distance and destroy a blockhouse on its way. On the other hand, a wall is so strongly built that can stop the bullets.
The goal is to place as many blockhouses in a city as possible so that no two can destroy each other. A configuration of blockhouses is legal provided that no two blockhouses are on the same horizontal row or vertical column in a map unless there is at least one wall separating them. In this problem we will consider small square cities (at most 4x4) that contain walls through which bullets cannot run through.
The following image shows five pictures of the same board. The first picture is the empty board, the second and third pictures show legal configurations, and the fourth and fifth pictures show illegal configurations. For this board, the maximum number of blockhouses in a legal configuration is 5; the second picture shows one way to do it, but there are several other ways.
Your task is to write a program that, given a description of a map, calculates the maximum number of blockhouses that can be placed in the city in a legal configuration.
Input
Output
Sample Input
4
.X..
....
XX..
....
2
XX
.X
3
.X.
X.X
.X.
3
...
.XX
.XX
4
....
....
....
....
0
Sample Output
5
1
5
2
4
题意:
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;/*
int cmp(const void *a,const void *b){
return *(int*)a-*(int*)b;
}*/
int count(int a[4][4],int row,int col,int n){/*数数,计算每个空位,十字架方向上所有能够放的,即会发生冲突的数目*/
int count1=0,i;/*注意四个方向,count计数,别忘了设初值为0*/
for(i=row-1;i>=0;i--){/*up*/
if(a[i][col]==2)/*碰到墙才会停止*/
break;
else
count1++;
}
for(i=row+1;i<n;i++){/*down*/
if(a[i][col]==2)
break;
else
count1++;
}
for(i=col-1;i>=0;i--){/*left*/
if(a[row][i]==2)
break;
else
count1++;
}
for(i=col+1;i<n;i++){/*right*/
if(a[row][i]==2)
break;
else
count1++;
}
return count1;
}
bool right(int a[4][4],int row,int col,int n){/*判断是否可以安置炮*/
int i;
for(i=row-1;i>=0;i--){/*用bool型*/
if(a[i][col]==1)/*十字架方向上碰到架炮的地方,就说明有冲突,即此处不可行*/
return false;
else if(a[i][col]==2)/*碰到墙停止*/
break;
}
//down
for(i=row+1;i<n;i++){/*仍旧是四个方向上检测*/
if(a[i][col]==1)
return false;
else if(a[i][col]==2)
break;
}
//left
for(i=col-1;i>=0;i--){
if(a[row][i]==2)
break;
else if(a[row][i]==1)
return false;
}
//right
for(i=col+1;i<n;i++){
if(a[row][i]==2)
break;
else if(a[row][i]==1)
return false;
}
return true;
}
int main(){
int n,i,j,k,ans;
char c;
int map[4][4];
int cnt[4][4];
while(scanf("%d",&n),n){
k=0,ans=0;
memset(cnt,-1,sizeof(cnt));
for(i=0;i<n;i++){
for(j=0;j<n;j++){
// scanf("%c",&c);
cin>>c;
if(c=='.'){/*将字符型的图转化成数组型的*/
k++;/*顺表记录下总共有多少个空的位置,方便最后检测成不成功时的循环次数*/
map[i][j]=0;/*0表示可放的位置*/
}
else if(c=='X')/*X表示墙的位置*/
map[i][j]=2;
}
}
for(i=0;i<n;i++){/*计数,遇墙跳过,遇空地计数,并将地址与数目用二维数组cnt[i][j]保留下来*/
for(j=0;j<n;j++){
if(map[i][j]==2)
continue;
else
cnt[i][j]=count(map,i,j,n);
}
}
/*qsort(cnt,n*n,sizeof(cnt[0][0]),cmp);//!!!不能使用qsort直接对cnt排序,否则将会把位置给弄丢,所以应该使用冒泡排序*/
int min=7,mini,minj;/*最多只能是6,用题中的最大可能做最小箱的箱底*/
while(k--){/*有k个空位,即有k种可能性,每个位置都要判断下*/
for(i=0;i<n;i++){
for(j=0;j<n;j++){
if(cnt[i][j]==-1)
continue;
else if(cnt[i][j]<min){/*要先排排序,从最小的开始,使用贪心,因为周围的可能最少,该位成功的可能性最大*/
min=cnt[i][j];/*重置最小*/
mini=i;/*记录位置*/
minj=j;
}
}
}
if(right(map,mini,minj,n)){/*判断是否能够放*/
map[mini][minj]=1;/*可以的话,就将map中的该位置为1,标志为有炮,便于剩下位置的判断*/
ans++;/*成立计数加1*/
}
cnt[mini][minj]=-1;/*该位置不用再检测了,在cnt数组中标记下-1,直接跳过,检测第二个最小的位置*/
min=7;/*重置最小*/
}
/*“。”点表示可放东西,总计有多少个空,k个*/
/* for(i=0;i<n;i++){
for(j=0;j<n;j++){
if(cnt[i][j]==-1)
continue;
else if(right(map,i,j,n)){
map[i][j]=1;
ans++;
}
}
}*/
printf("%d\n",ans);/*输出*/
}
return 0;
}