回 帖 发 新 帖 刷新版面

主题:恺撒的规划问题

亚特兰蒂斯是一块富饶美丽的土地。恺撒大帝率领他的大军,经过了一整年的浴血奋战,终于将它纳入了罗马帝国的版图。然而,长期的战火彻底抹去了这里的繁华,昔日的富庶之地如今一片荒芜。恺撒大帝作为一位有着雄才大略的君主,决心在战争的废墟上建起一座更为宏伟的城市。所以,在建城之前,他需要对整个城市进行规划。

  亚特兰蒂斯是一块矩形平原,恺撒准备在上面修建一些建筑。为了规划方便,他将矩形划分成N*M格。棘手的是,部分古老的神庙残存下来,散布在某些格子内。亚特兰蒂斯的原住民原本就十分信奉神灵,而这些经过战火洗礼的神庙更是被他们视为圣物,是万万不能拆除的,否则将激起民愤,甚至引发暴动。恺撒深知这一点,因此,他的新建筑在选址时要避开这些神庙。

假设新的建筑物有P种规格,每种建筑物都是正方形的,占地为Ti Ti格 (1<=i<=P)。恺撒想知道对于每种规格的建筑,有多少种不同的合适选址方案(一种合适的选址方案指的是在该建筑所占的正方形区域内不存在神庙)。作为他的内务部长,这个光荣而艰巨的任务自然交给你来完成。

【输入】

  输入文件第一行包含三个数,分别代表N,M,P (1<=N,M<=100,1<=P<=100)。随后的n行,每行有m个0或1(1表示该格为废墟,0表示该格有神庙)。接下来的P行每行有一个整数 (1< <=max(M,N)),代表的第i种建筑物的边长。

【输出】

输出文件有P行,每行一个整数,第行的数代表边长为 的建筑物选址方案数。

【样例输入】

4 4 2
1011
1111
1110
1110
2
3

【样例输出】

5
1

                                          大家都来作一下吧~~~~~~~~~~~~

回复列表 (共3个回复)

沙发

昨天花了一整天的时间研究你这个恺撒的问题,写了两个程序,
第一个比第二个要好,试鉴赏.(已调试,未做解释,见谅)
#include "stdio.h"
#include "stdlib.h"
#include "process.h"
#define SUCCESS 1
#define FAIL 0
#define YES 1
#define NO 0


void pseek(int*,int*,int,int,int,int,int);

int sum;

void main(void)
{
int m,n,p,*plane,i,j,k,x,y,t;
int *isseek;
FILE*fin,*fout;
if(!(fin=fopen("f:\\ty.txt","r")))
{
  printf("f:\\ty.txt cann't be found\n");
  exit(0);
}
if(!(fout=fopen("f:\\tx.txt","w")))
{
  printf("f:\\tx.txt cann't be found\n");
  exit(0);
}
rewind(fin);
fscanf(fin,"%d %d %d",&n,&m,&p);
plane=(int*)malloc(m*n*sizeof(int));
isseek=(int*)malloc(m*n*sizeof(int));
for(i=0;i<n;i++)
for(j=0;j<m;j++)
fscanf(fin,"%d",&plane[m*i+j]);
for(i=0;i<p;i++)
{
  x=y=sum=0;
  for(t=0;t<n;t++)
  for(j=0;j<m;j++)
  isseek[m*t+j]=0;
  fscanf(fin,"%d",&k);
  pseek(isseek,plane,n,m,k,x,y);
  fprintf(fout,"%d\n",sum);
}
}

void pseek(int*isseek,int*plane,int n,int m,int k,int x,int y)
{
int result=SUCCESS;
int colx=x,linx=x,liny=y,coly=y;
int i,j;
for(i=x;i<x+k;i++)
for(j=y;j<y+k;j++)
if(!plane[m*i+j])
{
  result=FAIL;
  if(j>coly){colx=i;coly=j;}
  if(i>linx){linx=i;liny=j;}
}

if(result==SUCCESS)sum++;
coly++;
linx++;
isseek[m*x+y]=YES;
if(colx+k<=n&&coly+k<=m&&isseek[m*colx+coly]==NO)
pseek(isseek,plane,n,m,k,colx,coly);
if(linx+k<=n&&liny+k<=m&&isseek[m*linx+liny]==NO)
pseek(isseek,plane,n,m,k,linx,liny);
}

输入文件(f:\ty.txt)的形式:
5 5 2
1 0 1 1 1
1 1 1 1 1
1 1 1 0 1
1 1 1 0 1
1 1 1 1 1
2
3
(f:\tx.txt)输出结果:
8
2
输入文件要注意空格.
#include "stdio.h"
#include "stdlib.h"
#include "process.h"
#define SUCCESS 1
#define FAIL 0
#define YES 1
#define NO 0

void pseek(int*,int*,int,int,int,int,int);

int sum;

void main(void)
{
int m,n,p,*isseek,*plane,i,j,t,k,x,y;
FILE*fin,*fout;
if(!(fin=fopen("f:\\ty.txt","r")))
{
  printf("f:\\ty.txt cann't be found\n");
  exit(0);
}
if(!(fout=fopen("f:\\tx.txt","w")))
{
  printf("f:\\tx.txt cann't be found\n");
  exit(0);
}
rewind(fin);
fscanf(fin,"%d %d %d",&n,&m,&p);
plane=(int*)malloc(m*n*sizeof(int));
isseek=(int*)malloc(m*n*sizeof(int));
for(i=0;i<n;i++)
for(j=0;j<m;j++)
fscanf(fin,"%d",&plane[m*i+j]);
for(i=0;i<p;i++)
{
  sum=x=y=0;
  for(t=0;t<n;t++)
  for(j=0;j<m;j++)
  isseek[m*t+j]=NO;
  fscanf(fin,"%d",&k);
  pseek(isseek,plane,n,m,k,x,y);
  fprintf(fout,"%d\n",sum);
}
}

void pseek(int*isseek,int*plane,int n,int m,int k,int x,int y)
{
int result=SUCCESS;
int colx=x,linx=x,liny=y,coly=y;
int i,j;
for(i=x;i<x+k;i++)
{
for(j=y;j<y+k;j++)
{
if(!plane[m*i+j])
{
  result=FAIL;
break;
}
}
if(result==FAIL)break;
}

if(result==SUCCESS)sum++;
coly++;
linx++;
isseek[m*x+y]=YES;
if(colx+k<=n&&coly+k<=m&&isseek[m*colx+coly]==NO)
pseek(isseek,plane,n,m,k,colx,coly);
if(linx+k<=n&&liny+k<=m&&isseek[m*linx+liny]==NO)
pseek(isseek,plane,n,m,k,linx,liny);
}




板凳

来一点注释不行么?本人C水平有限,我学Pascal~~~~~~~~~

3 楼

很明显,我用了递归算法.
我的算法是:
先搜索一个p*p块,然后则分俩路,一横一竖,继续搜索.
search()
{
若无寺庙
{
横的新块左上角x坐标+1,y坐标不变.search();
竖的新块左上角y坐标+1,x坐标不变.search();
}
若有寺庙
{
找出块内x坐标最大的寺庙,横的新块的x坐标即使改寺庙的x坐标+1,y不变.search();
找出块内y坐标最大的寺庙,竖的新块的y坐标即使改寺庙的y坐标+1,y不变.search();
}
}

当然你很容易发现搜索中可能会出现块的重复搜索.
于是我用了标记数组isseek;

本人解说能力有限,若不懂,吾已无可奈何.

我来回复

您尚未登录,请登录后再回复。点此登录或注册