hdu 1045 Fire Net

来源:互联网 发布:如何自学app编程 编辑:程序博客网 时间:2024/06/11 10:00
//题目大意:给一个最大不超过4x4的图,用X表示墙壁,问能在这张图上放多少个碉堡,每个碉堡可以向上,下,左,右四个方向发射子弹,但是墙可以挡住子弹,我们希望在放置最多碉堡的情况下,保证两两碉堡不会相互攻击到对方  
//最优策略:尽量在墙的四周放置碉堡。
//先将每个墙的位置记录下来,在墙的四周(上下左右放碉堡是最好的),按墙四周的所能安放碉堡的数目排序
//比如 . .X2    X1这个墙四周可以放4个碉堡,排在前面,下一个X2周围只能放两个排在后面
//         .X1.
//          . . .
//遍历每一个墙,在墙的周围放上碉堡,当然了,放置的时候还要判断该位置能否放碉堡。

//遍历完后,还要重新遍历整个图,防止没有墙壁以及 墙壁数量较少导致遗漏的情况。 

//因为墙壁隔着两者不会相互攻击,所以不是二分图的情况

#include<iostream>#include<cstdio>#include<memory>#include<algorithm>using namespace std;struct Z{int x;int y;int kong;}z[17];//黑块 int map[5][5];int n;//4int cmp(Z a,Z b){return a.kong>b.kong;}int testR(int r,int c)//判断r行是否允许安放碉堡 {int flagL=1;//左边允许标志 int flagR=1;//右边允许标志 if(c==1){//如果在第一列,向右扫描 for(;c<=n;c++){if(map[r][c]=='.')continue;if(map[r][c]=='X')break;if(map[r][c]=='N'){flagR=0;break;}//break;}}else if(c==n){//如果在最后一列,向左扫描 for(;c>=1;c--){if(map[r][c]=='.')continue;if(map[r][c]=='X')break;if(map[r][c]=='N'){flagL=0;break;}//break;}}else{//如果在中间 int zuo=c-1;int you=c+1;for(;you<=n;you++){if(map[r][you]=='.')continue;if(map[r][you]=='X')break;if(map[r][you]=='N'){flagR=0;break;}//break;} for(;zuo>=1;zuo--){if(map[r][zuo]=='.')continue;if(map[r][zuo]=='X')break;if(map[r][zuo]=='N'){flagL=0;break;}//break;}}return flagL && flagR;}int testC(int r,int c) //判断列c是否允许安放碉堡 {int flagup=1;int flagdown=1;if(r==1){//扫描下方 for(;r<=n;r++){if(map[r][c]=='.')continue;if(map[r][c]=='X')break;if(map[r][c]=='N'){flagdown=0;break;}//break;}}else if(r==n){//扫描上方 for(;r>=1;r--){if(map[r][c]=='.')continue;if(map[r][c]=='X')break;if(map[r][c]=='N'){flagup=0;break;}//break;}}else{int shang=r-1;int xia=r+1;for(;xia<=n;xia++){if(map[xia][c]=='.')continue;if(map[xia][c]=='X')break;if(map[xia][c]=='N'){flagdown=0;break;}//break;} for(;shang>=1;shang--){if(map[shang][c]=='.')continue;if(map[shang][c]=='X')break;if(map[shang][c]=='N'){flagup=0;break;}//break;}}return flagup && flagdown;}int main(){scanf("%d",&n);while(n){int i,j;int pos=0;for(i=1;i<=n;i++){getchar();for(j=1;j<=n;j++){scanf("%c",&map[i][j]);if(map[i][j]=='X'){z[pos].x=i;z[pos].y=j;pos++;}} }int k=0;for(i=1;i<=n;i++) //统计每个墙周围能安放碉堡的个数 {for(j=1;j<=n;j++){if(map[i][j]=='X'){int cnt=0;if(i>=2 && map[i-1][j]=='.'){cnt++;}if(i<=n-1 && map[i+1][j]=='.'){cnt++;}if(j<=n-1 && map[i][j+1]=='.'){cnt++;}if(j>=2 && map[i][j-1]=='.'){cnt++;}z[k].kong=cnt;k++;}}}sort(z,z+pos,cmp); //排序 int ans=0;for(i=0;i<pos;i++)//遍历每一个墙 {int x=z[i].x;int y=z[i].y;//上和下,列不变 int shang=x-1;if(shang>=1 && map[shang][y]=='.')//如果这个位置没有东西 {if(testR(shang,y))//如果这个行可以放 {if(testC(shang,y)){map[shang][y]='N';ans++;}}} int xia=x+1;if(xia<=n &&map[xia][y]=='.'){if(testR(xia,y))//如果这个行可以放 {if(testC(xia,y)){map[xia][y]='N';ans++;}}}//左和右行不变 int zuo=y-1;int you=y+1;if(zuo>=1 && map[x][zuo]=='.'){if(testR(x,zuo))//如果这个行可以放 {if(testC(x,zuo)){map[x][zuo]='N';ans++;}}} if(you<=n && map[x][you]=='.'){if(testR(x,you))//如果这个行可以放 {if(testC(x,you)){map[x][you]='N';ans++;}}} }for(i=1;i<=n;i++) //补漏 {for(j=1;j<=n;j++){if(map[i][j]=='.'){if(testR(i,j)&&testC(i,j)){map[i][j]='N';ans++;}}}}//for(i=1;i<=n;i++)//{//for(j=1;j<=n;j++)//{//printf("%c ",map[i][j]);//}//printf("\n");//}printf("%d\n",ans);scanf("%d",&n);}return 0;}


原创粉丝点击