SWUN 1303 - 魔法学徒


魔法学徒

时间限制(普通/Java) : 2000 MS/ 3000 MS          运行内存限制 : 65536 KByte
总提交 : 20            测试通过 : 6

描述

   这里有一个N*M的大型矩阵,当中充满了0或1。

   小魔法师phk童鞋想从这个大型矩阵中找出一个最大子矩阵,并且这个最大子矩阵全部由1组成。

   当然当了18年蹩脚的魔法学徒,他总是有那么点特殊能力的。虽然魔力有限,但他还是能施展一次变换术,这招可以毫无道理地将大型矩阵中的一整行全部变成1,然后再去找最大子矩阵。

   尽管这样,但phk童鞋还是很难从大型矩阵中找到最大子矩阵,所以请你帮忙寻找

 

 

输入

这里有多组测试数据,第一行为两个数字,N,M(1<=N,M<=100),接下来N*M个整数,表示一个矩阵。

输出

输出最大的子矩阵大小。

样例输入

2 2
00
11

样例输出

4

提示

 

题目来源

HLY


 

题目地址:http://218.194.91.48/acmhome/problemdetail.do?&method=showdetail&id=1303

 

利用到这题的一点思路:http://blog.csdn.net/diannaok/article/details/7796441

 

其余就是纯暴力枚举了。。。

 

=========================================================================================================== 

以前的搓B写法:

 

#include<iostream>
#include<cstdio>
#include<algorithm>

using namespace std;

char mp[103][103];
int dp[103][103];
int l[103],r[103];

int main(){
	int i,j,k,n,m,mx,tmp;
	while(~scanf("%d%d",&n,&m)){
		for(i=1;i<=n;i++) scanf("%s",mp[i]+1);
		mx=0;
		for(j=1;j<=m;j++) dp[0][j]=0;
		for(k=1;k<=n;k++){
			for(i=1;i<=n;i++)
				for(j=1;j<=m;j++)
					if(i==k || mp[i][j]=='1') dp[i][j]=dp[i-1][j]+1;
					else dp[i][j]=0;
			for(i=1;i<=n;i++){
				for(j=0;j<=m+1;j++) l[j]=r[j]=j;
				dp[i][0]=dp[i][m+1]=-1;
				for(j=1;j<=m;j++)
					while(dp[i][l[j]-1]>=dp[i][j])
						l[j]=l[l[j]-1];
				for(j=m;j>=1;j--)
					while(dp[i][r[j]+1]>=dp[i][j])
						r[j]=r[r[j]+1];
				for(j=1;j<=m;j++){
					tmp=(r[j]-l[j]+1)*dp[i][j];
					if(tmp>mx) mx=tmp;
				}
			}
		}
		printf("%d\n",mx);
	}
	return 0;
}


 

===========================================================================================================

 

新学的写法:

 

#include<iostream>
#include<cstdio>

using namespace std;

char s[102][102];
int n,m;

short get_res(){
	short h[102],l[102],r[102],i,j,lm,rm,k,res=0,tmp;
	for(k=0;k<n;k++){
		for(j=0;j<m;j++)
			h[j]=0,l[j]=0,r[j]=m-1;
		for(i=0;i<n;i++){
			lm=0,rm=m-1;
			for(j=0;j<m;j++)
				if(s[i][j]=='1' || k==i){
					h[j]++;
					if(lm>l[j]) l[j]=lm;
				}
				else lm=j+1,h[j]=0,l[j]=0;
			for(j=m-1;j>=0;j--)
				if(h[j]){
					if(rm<r[j]) r[j]=rm;
					tmp=(r[j]-l[j]+1)*h[j];
					if(tmp>res) res=tmp;
				}
				else rm=j-1,r[j]=m-1;
		}
	}
	return res;	
}

int main(){
	while(~scanf("%d%d",&n,&m)){
		for(int i=0;i<n;i++) scanf("%s",s[i]);
		printf("%d\n",get_res());
	}
	return 0;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值