2015 程序设计实习之深搜+广搜作业

A:棋盘问题

//广搜问题,用一个结构体来记录,结构体加数组,然后记录pre ,真是简介明了
#include<iostream>
#include<stdio.h>
using namespace std;
int maze[5][5];
int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
struct node
{
    int x,y;
    int pre;
}p[1000];
bool is(int x,int y)
{
    if(x>=0&&x<=4&&y>=0&&y<=4)
        return true;
    else
        return false;
}
void print(int x_)
{
    if(p[x_].pre==-1)
        return;
    print(p[x_].pre);
    printf("(%d, %d)\n",p[x_].x,p[x_].y);
    return;
}
void bfs(int x_,int y_)
{
    p[0].x=x_;
    p[0].y=y_;
    p[0].pre=-1;
    int front=0,rear=1;
    while(front<rear)
    {
        for(int i=0;i<4;++i)
        {
            int tempx=p[front].x+dx[i];
            int tempy=p[front].y+dy[i];
            if(is(tempx,tempy)&&maze[tempx][tempy]==0)
            {
                maze[tempx][tempy]=1;
                p[rear].x=tempx;
                p[rear].y=tempy;
                p[rear].pre=front;
                rear++;
            }
            if(tempx==4&&tempy==4)
            {
                print(front);
                return ;
            }
        }
        front++;
    }
    return ;
}
int main()
{
    for(int i=0;i<5;++i)
        for(int j=0;j<5;++j)
            cin>>maze[i][j];
    printf("(0, 0)\n");
    bfs(0,0);
    printf("(4, 4)\n");
    return 0;
}


总时间限制: 
1000ms 
内存限制: 
65536kB
描述
在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C。
输入
输入含有多组测试数据。
每组数据的第一行是两个正整数,n k,用一个空格隔开,表示了将在一个n*n的矩阵内描述棋盘,以及摆放棋子的数目。 n <= 8 , k <= n
当为-1 -1时表示输入结束。
随后的n行描述了棋盘的形状:每行有n个字符,其中 # 表示棋盘区域, . 表示空白区域(数据保证不出现多余的空白行或者空白列)。
输出
对于每一组数据,给出一行输出,输出摆放的方案数目C (数据保证C<2^31)。
样例输入
2 1
#.
.#
4 4
...#
..#.
.#..
#...
-1 -1
样例输出
2
1
来源

蔡错@pku


#include<iostream>
#include<memory.h>
using namespace std;
int table[8][8];
int sol;
int side,num;
int mark[8];
void dfs(int row,int n)
{
    if(n==0)
    {
        sol++;
        return ;
    }
    if(row<0)
        return ;
    for(int i=0;i<side;++i)
    {
        if(table[row][i]==1&&mark[i]==0)
        {
            mark[i]=1;
            dfs(row-1,n-1);
            mark[i]=0;
        }
    }
    dfs(row-1,n);//这一行要放与不要放两种
    return ;
}
int main()
{
    while(1){
        cin>>side>>num;
        if(side==-1&&num==-1)
            break;
        char ch;
        memset(mark,0,sizeof(mark));
        sol=0;
        for(int i=0;i<side;++i)
            for(int j=0;j<side;++j)
            {
                cin>>ch;
                if(ch=='.')
                    table[i][j]=0;
                if(ch=='#')
                    table[i][j]=1;
            }
        dfs(side-1,num);
        cout<<sol<<endl;
    }
    return 0;
}

B:生日蛋糕

总时间限制: 
5000ms 
内存限制: 
65536kB
描述
7月17日是Mr.W的生日,ACM-THU为此要制作一个体积为Nπ的M层生日蛋糕,每层都是一个圆柱体。
设从下往上数第i(1 <= i <= M)层蛋糕是半径为Ri, 高度为Hi的圆柱。当i < M时,要求Ri > Ri+1且Hi > Hi+1。
由于要在蛋糕上抹奶油,为尽可能节约经费,我们希望蛋糕外表面(最下一层的下底面除外)的面积Q最小。
令Q = Sπ
请编程对给出的N和M,找出蛋糕的制作方案(适当的Ri和Hi的值),使S最小。
(除Q外,以上所有数据皆为正整数)
输入
有两行,第一行为N(N <= 10000),表示待制作的蛋糕的体积为Nπ;第二行为M(M <= 20),表示蛋糕的层数为M。
输出
仅一行,是一个正整数S(若无解则S = 0)。
样例输入
100
2
样例输出
68
提示
圆柱公式
体积V = πR 2H
侧面积A' = 2πRH
底面积A = πR 2
来源
Noi 99
//这道题的剪枝想法很重要,一是对最大最小值的估计,区间段,二是对平均值
#include<iostream>
#include<cmath>
#include<algorithm>
#include<memory.h>
using namespace std;
int mins=0,s;
int minS[30],minV[30];  //i行及以上各行的最小表面积
void dfs(int r,int h,int lefts,int leftv)//传进去的参数是上一个回合的r h 和剩下的层数和体积
{
    if(lefts==0&&leftv==0)
    {
        if(mins==0)
            mins=s;
        else
            mins=min(mins,s);
        return;
    }
    if(lefts==0||leftv==0)
        return;
    if(r*h*r<(leftv/lefts))  //上一步的面积大于剩下的平均值,就要放弃,这步剪枝很重要
        return;
    if(h==1||r==1)
        return;
    if(h<=lefts||r<=lefts)
        return;
    if(minV[lefts]>leftv)     //对最小值的估计
        return;
    if(mins&&(s+minS[lefts])>mins)    //对最小面积的估计
        return ;
    for(int i=r-1;i>=lefts;--i)
        for(int j=h-1;j>=lefts;--j)
        {
            int tempv=i*i*j;
            if(tempv>leftv)
                continue;
            else
            {
                s+=2*i*j;
                if(mins&&s>=mins)
                {
                    s-=2*i*j;
                    continue;
                }
                dfs(i,j,lefts-1,leftv-tempv);
                s-=2*i*j;
            }
        }
    return ;
}
int main()
{
    int n,m;
    cin>>n>>m;//n--voloum,m--storey
    memset(minS,0,sizeof(minS));
    memset(minV,0,sizeof(minV));
    for(int i=1;i<=m;++i)
    {
        for(int j=1;j<=i;j++)
        {
            minS[i]+=2*j*j;
            minV[i]+=j*j*j;
        }
    }
    int maxr;
    maxr=sqrt(n/m);
    while(maxr*maxr*m>n)
        maxr-=1;
    for(int i=maxr;i>=m;--i)
    {
        int temph=n/(i*i);
        while(temph*i*i>n)
            temph-=1;
        if(temph<m)
            continue;
        s=i*i;
        for(int h=temph;h>=m;h--)
        {
            s+=2*i*h;
            if(mins&&s>=mins)
            {
                s-=2*i*h;
                continue;
            }
            dfs(i,h,m-1,n-i*i*h);
            s-=2*i*h;
        }
    }
    cout<<mins<<endl;
    return 0;
}

C:Flip Game

总时间限制: 
1000ms 
内存限制: 
65536kB
描述
Flip game is played on a rectangular 4x4 field with two-sided pieces placed on each of its 16 squares. One side of each piece is white and the other one is black and each piece is lying either it's black or white side up. Each round you flip 3 to 5 pieces, thus changing the color of their upper side from black to white and vice versa. The pieces to be flipped are chosen every round according to the following rules:
  1. Choose any one of the 16 pieces. 
  2. Flip the chosen piece and also all adjacent pieces to the left, to the right, to the top, and to the bottom of the chosen piece (if there are any).

Consider the following position as an example:

bwbw
wwww
bbwb
bwwb
Here "b" denotes pieces lying their black side up and "w" denotes pieces lying their white side up. If we choose to flip the 1st piece from the 3rd row (this choice is shown at the picture), then the field will become:

bwbw
bwww
wwwb
wwwb
The goal of the game is to flip either all pieces white side up or all pieces black side up. You are to write a program that will search for the minimum number of rounds needed to achieve this goal.
输入
The input consists of 4 lines with 4 characters "w" or "b" each that denote game field position.
输出
Write to the output file a single integer number - the minimum number of rounds needed to achieve the goal of the game from the given position. If the goal is initially achieved, then write 0. If it's impossible to achieve the goal, then write the word "Impossible" (without quotes).
样例输入
bwwb
bbwb
bwwb
bwww
样例输出
4
来源
Northeastern Europe 2000
#include<iostream>
#include<memory.h>
#include<algorithm>
using namespace std;
int table[5][6];
int press[5][6];
int p[2]={20,20};
bool is[2]={0,0};
bool guess(int tar)
{
    int tmp=0;
    for(int i=1;i<=4;++i)
        if(press[1][i]==1)
            tmp++;
    for(int i=2;i<=4;++i)
        for(int j=1;j<=4;++j)
        {press[i][j]=((table[i-1][j]+press[i-1][j]+press[i-1][j-1]+press[i-1][j+1]+press[i-2][j])%2)^tar;  //我用的是异或,及相同为0,不同为1
            if(press[i][j])
                tmp++;
        }
    for(int j=1;j<=4;++j)
        if((table[4][j]+press[3][j]+press[4][j-1]+press[4][j+1]+press[4][j])%2!=tar)
            return false;
    if(is[tar])
        p[tar]=(p[tar]<tmp)?p[tar]:tmp;
    else{
        p[tar]=tmp;
        is[tar]=1;
    }
    return true;
}
void  perform(int tar)
{
    while(1)
    {
        guess(tar);
        press[1][1]++;
        int c=1;
        while(press[1][c]>1)
        {
            press[1][c]=0;
            c++;
            press[1][c]++;
        }
        if(c==5)
            break;   //这里的限制条件!!
    }
}
int main()
{
    char ch;
    memset(table,0,sizeof(table));
    memset(press,0,sizeof(press));
    for(int i=1;i<=4;++i)
        for(int j=1;j<=4;++j)
        {
            cin>>ch;
            if(ch=='b')
                table[i][j]=1;//b--0;w--1
            else
                table[i][j]=0;
        }
    perform(0);
    memset(press,0,sizeof(press));//这时候要清零,不然会有麻烦,在这里也被坑了好久
    perform(1);
    if(is[0]||is[1])
        cout<<min(p[0],p[1])<<endl;
    else
        cout<<"Impossible"<<endl;
    return 0;
}


D:迷宫问题

总时间限制: 
1000ms 
内存限制: 
65536kB
描述

定义一个二维数组: 

int maze[5][5] = {

0, 1, 0, 0, 0,

0, 1, 0, 1, 0,

0, 0, 0, 0, 0,

0, 1, 1, 1, 0,

0, 0, 0, 1, 0,

};


它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线。


输入
一个5 × 5的二维数组,表示一个迷宫。数据保证有唯一解。
输出
左上角到右下角的最短路径,格式如样例所示。
样例输入
0 1 0 0 0
0 1 0 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0
样例输出
(0, 0)
(1, 0)
(2, 0)
(2, 1)
(2, 2)
(2, 3)
(2, 4)
(3, 4)
(4, 4)
  • 查看 
  • 提交 
  • 统计 
  • 提问
    • //广搜问题,用一个结构体来记录,结构体加数组,然后记录pre ,真是简介明了
      #include<iostream>
      #include<stdio.h>
      using namespace std;
      int maze[5][5];
      int dx[4]={0,0,1,-1};
      int dy[4]={1,-1,0,0};
      struct node
      {
          int x,y;
          int pre;
      }p[1000];
      bool is(int x,int y)
      {
          if(x>=0&&x<=4&&y>=0&&y<=4)
              return true;
          else
              return false;
      }
      void print(int x_)
      {
          if(p[x_].pre==-1)
              return;
          print(p[x_].pre);
          printf("(%d, %d)\n",p[x_].x,p[x_].y);
          return;
      }
      void bfs(int x_,int y_)
      {
          p[0].x=x_;
          p[0].y=y_;
          p[0].pre=-1;
          int front=0,rear=1;
          while(front<rear)
          {
              for(int i=0;i<4;++i)
              {
                  int tempx=p[front].x+dx[i];
                  int tempy=p[front].y+dy[i];
                  if(is(tempx,tempy)&&maze[tempx][tempy]==0)
                  {
                      maze[tempx][tempy]=1;
                      p[rear].x=tempx;
                      p[rear].y=tempy;
                      p[rear].pre=front;
                      rear++;
                  }
                  if(tempx==4&&tempy==4)
                  {
                      print(front);
                      return ;
                  }
              }
              front++;
          }
          return ;
      }
      int main()
      {
          for(int i=0;i<5;++i)
              for(int j=0;j<5;++j)
                  cin>>maze[i][j];
          printf("(0, 0)\n");
          bfs(0,0);
          printf("(4, 4)\n");
          return 0;
      }



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值