浙江大学 ACM 1002题 (三种解法·转载)

①用C语言实现

#include<stdio.h>
#define MAX 4
#define WALL -1
char map[MAX+2][MAX+2];
int size,max,cur,depth;
void test(){
    int i =depth/size +1, j =depth%size +1,n;
    if(depth>=size*size){
        if(cur>max) max =cur;
        return;
    }
    if(!map[i][j]){
        map[i][j] =1;
        for(n=i+1;map[n][j]!=WALL;n++) map[n][j]++;
        for(n=i-1;map[n][j]!=WALL;n--) map[n][j]++;
        for(n=j+1;map[i][n]!=WALL;n++) map[i][n]++;
        for(n=j-1;map[i][n]!=WALL;n--) map[i][n]++;
        depth++;
        cur++;
        test();
        cur--;
        depth--;
        for(n=i+1;map[n][j]!=WALL;n++) map[n][j]--;
        for(n=i-1;map[n][j]!=WALL;n--) map[n][j]--;
        for(n=j+1;map[i][n]!=WALL;n++) map[i][n]--;
        for(n=j-1;map[i][n]!=WALL;n--) map[i][n]--;
        map[i][j] =0;
    }
    depth++;
    test();
    depth--;
}
void main(){
    int i,j;
    while(scanf_s("%d",&size)!=EOF&&size>0){
        getchar();
        for(i=0;i<=size+1;i++) 
           map[0][i] =map[size+1][i] =map[i][0] =map[i][size+1] =WALL;//四面都是墙
        for(i=1;i<=size;i++){
           for(j=1;j<=size;j++) map[i][j] = (getchar()=='X')?WALL:0;//输入内部构造
           getchar();
        }
        max =cur =depth =0;
        test();
        printf("%d/n",max);
    }
}

②用C++实现标准库实现

#include <iostream>
#include <vector>
#include <string>
using namespace std;


enum Tag
{
  STREET=0,
  VISITED=1,
  WALL=2,
  ERROR=-1
};
class Point
{
  public:
    int x;
    int y;
};
int Transfer(char ch)
{
  switch(ch)
  {
    case '.':
      return STREET;  //street
      break;
    case 'X':
      return WALL;  //wall
      break;
    default:
      return ERROR; //wrong input
    break;
  }
}
void Readin(vector< vector<int> > &map, int n)
{
  for(int row=0;row<n;row++)
  {
    vector<int> r(n);
    string line;
    cin>>line;
    for(int col=0;col<n;col++)
      r[col]=Transfer(line[col]);
    map.push_back(r);
  }
}
void Scan(vector< vector<int> >& map, int i, int j, vector<Point>& pvec)
{
  int size=map.size();
  //backward
  for(int b=j-1;b>=0;b--)
  {
    if(map[i][b]==WALL)
    {
      break;
    }
    else if(map[i][b]==STREET)
    {
      map[i][b]=VISITED;
      Point pt;
      pt.x=i;
      pt.y=b;
      pvec.push_back(pt);
    }
  }
  //forward
  for(int f=j+1;f<size;f++)
  {
    if(map[i][f]==WALL)
    {
      break;
    }
    else if(map[i][f]==STREET)
    {
      map[i][f]=VISITED;
      Point pt;
      pt.x=i;
      pt.y=f;
      pvec.push_back(pt);
    }
  }
 
  //up
  for(int u=i-1;u>=0;u--)
  {
    if(map[u][j]==WALL)
    {
      break;
    }
    else if(map[u][j]==STREET)
    {
      map[u][j]=VISITED;
      Point pt;
      pt.x=u;
      pt.y=j;
      pvec.push_back(pt);
    }
  }
  //down
  for(int d=i+1;d<size;d++)
  {
    if(map[d][j]==WALL)
    {
      break;
    }  
    else if(map[d][j]==STREET)
    {
      map[d][j]=VISITED;
      Point pt;
      pt.x=d;
      pt.y=j;
      pvec.push_back(pt);
    }
  }
}
void ResetScan(vector< vector<int> >& map, vector<Point>& pvec)
{
  for(int k=0;k<pvec.size();k++)
  {
    Point pt=pvec[k];
    map[pt.x][pt.y]=STREET;
  }
}
bool FindStreet(vector< vector<int> >& map)
{
  int size=map.size();
  for(int i=0;i<size;i++)
    for(int j=0;j<size;j++)
      if(map[i][j]==STREET)
        return true;
  return false;
}
void DFS(vector< vector<int> >& map, int& max, int& count)
{
  if(!FindStreet(map))
  {
    max=max>count?max:count;
    return;
  }
 
  int size=map.size();
  for(int i=0;i<size;i++)
  {
    for(int j=0;j<size;j++)
    {
      if(map[i][j]==STREET)
      {
        map[i][j]=VISITED;
        count++;
        vector<Point> pvec;
        Scan(map, i, j, pvec);
        DFS(map, max, count);
    
        map[i][j]=STREET;
        count--;
        ResetScan(map, pvec);
      }
    }
  }
}
 
int main()
{
  int n;
  cin>>n;
  while(n!=0)
  {
    vector< vector<int> > Map;
    Readin(Map,n);
    int count=0;
    int max=0;
    DFS(Map, max, count);
    cout<<max<<endl;
    cin>>n;
  }
  return 0;
}
 
这个问题本质上是约束条件下的搜索问题。
这里使用DFS来做。只适合于问题规模不大的情况。
另外也可以使用二分图的匹配方法来做,时间复杂度要低。

③用C++队列实现

#i nclude<iostream>
#i nclude<math.h>
using std::cout;
using std::endl;
using std::cin;
//0 空格 1 被射击 2 房子 3 墙
struct  CiteSite
{
 int x,y;     //方格中的位置
    CiteSite(){}
 CiteSite(int i,int j){x=i;y=j;}
};
struct CityPic
{
 unsigned long Buf[2]; //用来压缩方格
 CityPic(){};
 CityPic(const CityPic &item){Buf[0]=item.Buf[0];Buf[1]=item.Buf[1];}
};
struct CityPics
{
int M;            //M*M
CityPic citypic;
};
template<class NodeEntry>
struct Node
{
 Node():Next(NULL){}
 Node(const NodeEntry &entry):Entry(entry){}
 NodeEntry Entry;
 Node *Next;
};
template<class NodeEntry>
class Queue 
{
public:
 Queue();                                      //构造函数
 ~Queue();                                     //析构函数
 bool         IsEmpty() const;                 //队列是否为空
 NodeEntry    Server();                        //返回并去掉队首元素
    void         Append(const NodeEntry &item);   //添加一个队尾元素
    void         Retrieve(NodeEntry &item) const; //取得队首元素
 int          Size()const;                     //队列现有元素个数   
 void         Clear();                         //队列清空
 int iCount;
    Node<NodeEntry> *Front,*Rear;
};
void GetCity(char Buf[][4],int M);                 //读取输入的方格
void InCode(CityPic& citypic,char Buf[][4]);       //方格编码
void OutCode(CityPic &citypic,char Buf[][4]);      //方格解码
void CopyBuf(char Buf[][4],char OldBuf[][4]);      //复制方格
int  SeachCity(char Buf[][4],int M,Queue<CiteSite> &CitySiteQueue);//将可建房的位置装入CitySiteQueue
bool IsCityPicInQueue(CityPic& citypic,Queue<CityPic> &queue);     //队列中是否存在该方格的编码
bool IsCityPicCanBeExpand(char Buf[][4],int M);                    //该方格是否可扩展
void ExpandCityPic(char Buf[][4],int x,int y,int M);               //扩展方格
int  CountHouse(char Buf[][4],int M);                              //计算方格中的房子数量
/***************************************************************************************/
/****************************************************************************************/
int main()
{
 CityPic citypic;              //方格编码
 Queue<CityPic> queue;         //方格编码队列
 CityPics citypics;            //带M的方格编码
 Queue<CityPics> CityPicsQueue;//带M的方格编码队列
    CiteSite citysite;            //方格中的位置坐标
 Queue<CiteSite> CitySiteQueue;//坐标队列
 bool bWorking=true;           //是否进行方格处理
 char   OldCityBuf[4][4]={0}; 
 char   CityBuf[4][4]={0};
 int M;
 cin>>M;
    while(M!=0)
 {
  GetCity(OldCityBuf,M);
        InCode(citypics.citypic,OldCityBuf);
        citypics.M=M;   //输入  带M的方格编码到CityPicsQueue             
     CityPicsQueue.Append(citypics);
  cin>>M;
 }
 while(CityPicsQueue.iCount>0)
 {
     citypics=CityPicsQueue.Server();
        M=citypics.M;
  OutCode(citypics.citypic,OldCityBuf);  //取得原始方格
  if(!IsCityPicCanBeExpand(OldCityBuf,M))
  {
   cout<<0<<endl;
   continue;
  }
  bWorking=true;
  while(bWorking)
  {
   SeachCity(OldCityBuf,M,CitySiteQueue);//装入坐标队列
   while(CitySiteQueue.iCount>0)
   {
   citysite=CitySiteQueue.Server();
    CopyBuf(CityBuf,OldCityBuf);
    ExpandCityPic(CityBuf,citysite.x,citysite.y,M);//扩展
    if(!IsCityPicCanBeExpand(CityBuf,M))
    {
     if(queue.iCount==0&&CitySiteQueue.iCount<=0)    
     {
      bWorking=false;
     cout<<CountHouse(CityBuf,M)<<endl;
     break;
     }
     else continue;
    }   
    InCode(citypic,CityBuf);//编码
    if(IsCityPicInQueue(citypic,queue))
    {
     continue;
    }
    queue.Append(citypic); //编码入队
   }
   if(bWorking)
   {
   citypic=queue.Server();  //取新编码
   OutCode(citypic,OldCityBuf);//解码
   }
  }
 }
 return 0;
}
/**************************************************************************************/
/**************************************************************************************/
void GetCity(char Buf[][4],int M)
{
 char c;
 memset(Buf,16,0);
 for(int i=0;i<M;i++)
  for(int j=0;j<M;j++)
  {
   cin>>c;
   if(c=='.') Buf[i][j]=0;
   else Buf[i][j]=3;
  }
}
void InCode(CityPic& citypic,char Buf[][4])
{
 memset(&citypic,sizeof(CityPic),0);
 citypic.Buf[0]=Buf[0][0]+
  Buf[0][1]*10+
  Buf[0][2]*100+
  Buf[0][3]*1000+
  Buf[1][0]*10000+
  Buf[1][1]*100000+
  Buf[1][2]*1000000+
  Buf[1][3]*10000000+
  Buf[2][0]*100000000;
 citypic.Buf[1]=Buf[2][1]+
  Buf[2][2]*10+
  Buf[2][3]*100+
  Buf[3][0]*1000+
  Buf[3][1]*10000+
  Buf[3][2]*100000+
  Buf[3][3]*1000000;
}
void OutCode(CityPic &citypic,char Buf[][4])
{
 memset(Buf,16,0);
 Buf[0][0]=citypic.Buf[0]%10;
 citypic.Buf[0]/=10;
 Buf[0][1]=citypic.Buf[0]%10;
 citypic.Buf[0]/=10;
 Buf[0][2]=citypic.Buf[0]%10;
 citypic.Buf[0]/=10;
 Buf[0][3]=citypic.Buf[0]%10;
 citypic.Buf[0]/=10;
 Buf[1][0]=citypic.Buf[0]%10;
 citypic.Buf[0]/=10;
 Buf[1][1]=citypic.Buf[0]%10;
 citypic.Buf[0]/=10;
 Buf[1][2]=citypic.Buf[0]%10;
 citypic.Buf[0]/=10;
 Buf[1][3]=citypic.Buf[0]%10;
 citypic.Buf[0]/=10;
 Buf[2][0]=citypic.Buf[0]%10;
 
 Buf[2][1]=citypic.Buf[1]%10;
 citypic.Buf[1]/=10;
 Buf[2][2]=citypic.Buf[1]%10;
 citypic.Buf[1]/=10;
 Buf[2][3]=citypic.Buf[1]%10;
 citypic.Buf[1]/=10;
 Buf[3][0]=citypic.Buf[1]%10;
 citypic.Buf[1]/=10;
 Buf[3][1]=citypic.Buf[1]%10;
 citypic.Buf[1]/=10;
 Buf[3][2]=citypic.Buf[1]%10;
 citypic.Buf[1]/=10;
 Buf[3][3]=citypic.Buf[1]%10;
}
void CopyBuf(char Buf[][4],char OldBuf[][4])
{
 for(int i=0;i<4;i++)
  for(int j=0;j<4;j++)
   Buf[i][j]=OldBuf[i][j];
}
int  SeachCity(char Buf[][4],int M,Queue<CiteSite> &CitySiteQueue)
{
 int r=0;
 for(int i=0;i<M;i++)
  for(int j=0;j<M;j++)
  {
   if(Buf[i][j]==0)
   {
    r++;
            CitySiteQueue.Append(CiteSite(i,j));
   }
  }
  return r;
}
bool IsCityPicInQueue(CityPic& citypic,Queue<CityPic>&queue)
{
 Node<CityPic> *pNode=queue.Front;
 int i=queue.iCount;
 while(i>0)
 {
  if((citypic.Buf[0]==pNode->Entry.Buf[0])&&(citypic.Buf[1]==pNode->Entry.Buf[1]))
   return true;
  pNode=pNode->Next;
  i--;
 }
 return false;
}
bool IsCityPicCanBeExpand(char Buf[][4],int M)
{
 for(int i=0;i<M;i++)
  for(int j=0;j<M;j++)
  {
   if(Buf[i][j]==0)
    return true;
  }
  return false;
}
void ExpandCityPic(char Buf[][4],int x,int y,int M)
{
 int i=x,j=y;
 Buf[x][y]=2;
 while(i>0)
 {
  if(Buf[i-1][y]!=3)
   Buf[i-1][y]=1;
  else break;
  i--;
 }
 i=x;
 while(i<M-1)
 {
  if(Buf[i+1][y]!=3)
   Buf[i+1][y]=1;
  else break;
  i++;
 }
 j=y;
 while(j>0)
 {
  if(Buf[x][j-1]!=3)
   Buf[x][j-1]=1;
  else break;
  j--;
 }
 j=y;
 while(j<M-1)
 {
  if(Buf[x][j+1]!=3)
   Buf[x][j+1]=1;
  else break;
  j++;
 }
}
int  CountHouse(char Buf[][4],int M)
{
 int r=0;
 for(int i=0;i<M;i++)
  for(int j=0;j<M;j++)
  {
   if(Buf[i][j]==2)
    r++;
  }
  return r;
}
/***********************************构造函数*******************************************/
template<class NodeEntry>
Queue<NodeEntry>::Queue()
{
 iCount=0;
 Front=Rear=NULL;
}
/***********************************析构函数*******************************************/
template<class NodeEntry>
Queue<NodeEntry>::~Queue()
{
 Clear();
}
/***********************************队列是否为空***************************************/
template<class NodeEntry>
bool Queue<NodeEntry>::IsEmpty() const
{
 return (iCount==0);
}
/*********************************返回并去掉队首元素**********************************/
template<class NodeEntry>
NodeEntry  Queue<NodeEntry>::Server()
{
 NodeEntry entry;
 if(Front==NULL)cout<<"The Queue is empty!/n";
    Node<NodeEntry> *pNode=Front;
    Front=Front->Next;
 entry=pNode->Entry;
 delete pNode;
 iCount--;
 if(iCount<=0) Front=Rear=NULL;
 return entry;
}
/*********************************添加一个队尾元素************************************/
template<class NodeEntry>
void  Queue<NodeEntry>::Append(const NodeEntry &item)
{
 Node<NodeEntry> *pNode=new Node<NodeEntry>(item);
 if(Rear==NULL) Front=Rear=pNode;
 else
 {
  Rear->Next=pNode;
  Rear=pNode;
 }
 iCount++;
}
/********************************取得队首元素*****************************************/
template<class NodeEntry>
void  Queue<NodeEntry>::Retrieve(NodeEntry &item) const
{
 item=Front->Entry;
}
/*******************************队列现有元素个数***************************************/
template<class NodeEntry>
int   Queue<NodeEntry>::Size()const
{
 return iCount;
}
/*******************************队列清空***********************************************/
template<class NodeEntry>
void  Queue<NodeEntry>::Clear()
{
 Node<NodeEntry> *pNode;
 while(iCount>0)
 {
  pNode=Front;
  Front=Front->Next;
  delete pNode;
  iCount--;
 }
 Front=Rear=NULL;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值