杭电ACM——建房子(贪心)

突破口:充分利用每一堵墙,有墙出现,其所在的行、列都加权1(除非遇到另一堵墙才停止),依次从权值由高到低开始建,每建一座,其所在的行、列都设置为N(no)(除非遇到墙才停止)。

代码如下:

#include<cstdio>
#include<cstring>
#include<cctype>
using namespace std;
char map[6][6];  //制作一张图
struct wall   //记录墙的位置
{
	int x,y;
}w[17];
int main()
{
	int n,flag;
	int i,j,k;
	int yes,no,num;
	while(~scanf("%d",&n)&&n)
	{
		flag=0;k=0;
		for(i=0;i<=16;i++)  
		    w[i].x=w[i].y=0;
		for(i=1;i<=n;i++)
		{getchar();
			for(j=1;j<=n;j++)
			{
				scanf("%c",&map[i][j]);
				if(map[i][j]=='.')  //如果为'.',就将它改为‘0’,表示初始权值为0
				    map[i][j]='0';
				else if(map[i][j]=='X') //遇到墙,记录墙的位置及个数
				{
					flag++;
					w[k].x=i;w[k].y=j;k++;
				}
			}
		}
		if(flag==0) printf("%d\n",n); //没有墙的情况
		else
		{
			if(n==1) printf("0\n"); //n==1还有n==2的情况很简单,讨论一下就好了
			else if(n==2)
			{
				if(flag==1) printf("2\n");
				else if(flag==2)
				{
					if(w[0].x!=w[1].x&&w[0].y!=w[1].y)  //不同列不同行的才能两个 
					    printf("2\n");
					else printf("1\n");
				}
				else if(flag==3) printf("1\n");
				else printf("0\n");
			}
			else  //n==3或n==4的情况就比较复杂
			{
				yes=no=num=0;
				for(i=0;i<k;i++)/以墙为定点,向所在行、列加权
				{
					for(j=w[i].y+1;j<=n;j++) 
					{
						if(map[ w[i].x ][j]!='X')
						    map[w[i].x][j]++;
						else  break;  //遇到墙就要停了,下同
					}
					for(j=w[i].y-1;j>=1;j--)
					{
						if(map[ w[i].x ][j]!='X')
						    map[w[i].x][j]++;
						else break;
					}
					for(j=w[i].x+1;j<=n;j++)
					{
						if(map[j][ w[i].y ]!='X')
						    map[j][w[i].y]++;
						else	 break;
					}
					for(j=w[i].x-1;j>=1;j--)
					{
						if(map[j][ w[i].y ]!='X')
						    map[j][w[i].y]++;
						else  break;
					}
				}
				for(num=4;num>=0;num--)  //num表权值,最大为4
				{					
				    if(yes+no+flag==n*n) break;  //图填满了就不用继续了
					for(i=1;i<=n;i++)
					{
						for(j=1;j<=n;j++)
						{
							if((map[i][j]-'0')==num)
							{
								map[i][j]='Y';yes++;  
								for(k=j+1;k<=n;k++) //以‘Y’为定点,向其所在行、列赋值为‘N’
								{
									if(isdigit(map[i][k]))
									{
									    map[i][k]='N';no++;
									}
									else if(map[i][k]=='X') break; //遇到墙一定要停,下同
									
								}
								for(k=j-1;k>=1;k--)
								{
							    	if(isdigit(map[i][k]))
							  		{
									    map[i][k]='N';no++;
									}
									else if(map[i][k]=='X') break;
								}
								for(k=i+1;k<=n;k++)
								{
									if(isdigit(map[k][j]))
									{	
									    map[k][j]='N';no++;
								   }
								   else if(map[k][j]=='X') break;
								 }
								 for(k=i-1;k>=1;k--)
								 {
								 	if(isdigit(map[k][j]))
									{	
									    map[k][j]='N';no++;
								   }
								   else if(map[k][j]=='X') break;
								 }
							}
						}
					}
				}
				printf("%d\n",yes);
			}
		}
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值