六月搜索模拟


显示图像(bit)
【问题描述】
古老的显示屏是由N×M个象素(Pixel)点组成的。一个象素点的位置是根据所在行数和列数决定的。例如P(2,1)表示第2行第1列的象素点。那时候,屏幕只能显示黑与白两种颜色,人们用二进制0和1来表示。0表示黑色,1表示白色。当计算机发出一个指令:P(x,y)=1,则屏幕上的第x行第y列的阴极射线管就开始工作,使该象素点显示白色,若P(x,y)=0,则对应位置的阴极射线管不工作,象素点保持黑色。在某一单位时刻,计算机以N×M二维01矩阵的方式发出显示整个屏幕图像的命令。
例如,屏幕是由3×4象素点组成,在某单位时刻,计算机发出如下命令:
0001
0011
0110
距离定义:P1(x1,y1)和P2(x2,y2),距D(P1,P2):D(P1,P2)=|x1-x2|+|y1-y2|;
科学家们期望知道,每个象素点和其最近的显示白色的象素点之间的距离是多少——保证屏幕上至少有一个显示白色的象素点。
上面的例子中,象素P(1,1)与最近的白色象素点之间的距离为3,而象素P(3,2)本身显示白色,所以最短距离为0。

题目简述(bit):

一个图中所有点到1的最近距离;


输入格式:
第一行有两个数字,N和M (1<=N,M<=1000)。
以下N行,每行M个数字,0或1。
【输出格式】
输出文件有N行,每行M个数字,用1个空格分开。表示(i,j)离最近的白色象素点的距离。
【输入样例】

3 4
0001
0011
0110
【输出样例】
3 2 1 0
2 1 0 0
1 0 0 1
【数据范围】

对于30%的数据:N*M<=10000;
对于100%的数据:N*M<=1000^2。

分析:

搜索策略:bfs

当时是记录一遍,再扫一遍,找到1,就bfs;

值得借鉴的是:本题特点是多点同时搜索,可以用队列数组记录

出现1的坐标,这样可以同时开始,且不需多点间距离大小判断;

#include<cstdio>
#include<iostream>
#include<cstring>
#define INS 1001
using namespace std;
int n,m,p;
const int mx[]={0,0,-1,1},my[]={1,-1,0,0};
char ch[INS];
int ans[INS][INS];
int qx[1000000],qy[1000000];
void bfs();
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
         cin>>ch;//字符串输入;
         for(int j=0;j<m;j++)
         if(ch[j]=='1') ans[i][j+1]=1,p++,qx[p]=i,qy[p]=j+1;//读到1入队,记录答案;
    }
    bfs();
    for(int i=1;i<=n;i++)
    {
    for(int j=1;j<=m;j++)
        printf("%d ",ans[i][j]-1);
        printf("\n");
    }
    return 0;
}
void bfs()
{
    int h=0,t=p;
    while(h<t){
        h++;
        for(int i=0;i<4;i++){
            int xx=qx[h]+mx[i];
            int yy=qy[h]+my[i];
            if(xx>0&&yy>0&&xx<=n&&yy<=m&&ans[xx][yy]==0)
            {
                t++;
                qx[t]=xx;
                qy[t]=yy;
                ans[xx][yy]=ans[qx[h]][qy[h]]+1;
            }
        }
    }
}



生日蛋糕(cake)
【问题描述】
制作一个体积为Nπ的M层生日蛋糕,每层都是一个圆柱体。
设从下往上数第i(1<=i<=M)层蛋糕是半径为Ri, 高度为Hi的圆柱。

当i<M时,半径递减,高度递减,Ri、Hi均为整数。
在蛋糕上抹奶油,尽可能节约经费,我们希望蛋糕外表面(最下一层的下底面除外)的面积Q最小。
令Q= Sπ
请编程对给出的N和M,找出蛋糕的制作方案(适当的Ri和Hi的值),使S最小。
【输入格式】
输入最多10组数据,每组数据包含两个整数N和M。输入以一个0结尾。
【输出格式】
对于每组数据,输出一个整数S。
【输入样例】
100 2
1000 3
0
【输出样例】
68
316
【数据范围】
N<100001, M<11

分析:

1。搜索内容;

有层数,i,半径r,高度h,当前剩余体积v,当前表面积s;

2。3个减枝,比较难想,可行性,最优性减枝;

#include<iostream>
#include<cstdio>
#include<cmath>
#define f(i,a,b)    for(register int i=a;i<=b;++i)
#define fd(i,a,b)    for(register int i=a;i>=b;--i)
using namespace std;
const int N=20000+7;
int ans=987654321,n,m,Minv[N],Mins[N];
inline int read()//读入优化
{
      int num=0;
      char c;
      while(isspace(c=getchar()));
      while(num=num*10+c-48,isdigit(c=getchar()));
      return num;
}
bool flag=1;
inline void dfs(int now,int S,int V,int lasth,int lastr)
{
    if(now==0)//要是已经到了第一层就退出 
    {
        if(V==n)    ans=min(ans,S);//是否为合法答案 
        return;
    }
    //三重恶心的剪枝 
    if(S+2*(n-V)/lastr>ans)    return;
    //要是剩下体积除以最大(虽然取不到)半径=表面积,加上累计表面积>答案 退出 
    if(V+Minv[now]>n) return;//当前体积加上剩余层的最小体积还超过了约定体积,退出;
    if(S+Mins[now]>ans)    return;//最小面积+当前表面积>ans;
    fd(i,lastr-1,now)//从大到小枚举该层半径 
    {
        if(now==m)    S=i*i;//第一层那么加上顶上表面积 
        int Maxh=min(lasth-1,(n-V-Minv[now-1])/(i*i));
        fd(j,Maxh,now)//从大到小枚举该层高度 
            dfs(now-1,S+2*i*j,V+i*i*j,j,i);
    }
}
int main()
{
    n=read();m=read();
    f(i,1,m)
        Minv[i]=Minv[i-1]+i*i*i,//每一层的之后剩余最小体积;
        Mins[i]=Mins[i-1]+2*i*i;//每一层的最小表面积
    int MaxR=sqrt(n);
    dfs(m,0,0,n,MaxR);
    printf("%d",ans==987654321 ? 0 :ans);
    return 0;
}
其中几个判断边界比较难,先预处理每一层的最小半径和剩余体积;
没一层的最小高度和半径都是当前层数,因为递增且为整数;
海盗船(corsair)
【问题描述】
有一个很有趣的游戏叫做海盗船。这是一个在9*8的棋盘上进行的游戏,棋盘上的每个格子可能是下面4种状态之一:
“.”:表示当前格子为空;
“S”:表示你的船所在的位置;
“E”:表示敌船所在的位置;
“#”:表示一座小岛。
每次你可以将你的船朝周围的8个方向之一移动,但不能停留。在你移动完之后,所有的敌船会朝周围8个位置中和你的船当前位置距离最近的那个格子移动。在这个过程中,如果某艘敌船碰到了小岛,那么这艘敌船将会沉没。如果两艘敌船同时走到同一个格子中,那么这两艘敌船将会同时沉没,并且其残骸将会在该位置形成障碍,也就是说如果还有敌船走到这个位置,那么该敌船也会沉没。每艘敌船上都装了烈性炸药,如果你不幸让某艘敌船撞到了你,你就可以和我们敬仰的祖先欢聚一堂了。
现在你的任务是通过移动你的船来消灭所有的敌船,当然,在移动过程中,请确保你的船不要撞倒小岛或者敌船的残骸。
【输入格式】
输入文件第一行包含一个整数T,表示测试数据组数,以下每组数据包含一个9*8的地图,地图上的符号以及意义如题目所述。相邻的两组数据间用一个空行隔开。
【输出格式】
输出文件对于每组数据输出一行信息。如果你能够消灭所有的海盗船,那么输出“I'm the king of the Seven Seas!”,否则输出“Oh no! I'm a dead man!”。
【输入样例】
2
........
........
........
...E....
...#S...
........
........
........
.......E

........
........
.....E..
..E#.#..
....S...
...#.#E.
...E....
........
........
【输出样例】
I'm the king of the Seven Seas!
Oh no! I'm a dead man!
【数据范围】


状况:未解决;08年,6.7.13:31;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

徐行tag

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值