白银莲花池
(silvlily.pas/c/c++)

【问题描述】
         为了让同学们学习和锻炼,学校建造了一个美丽的池塘。这个长方形的池子被分成了M行N列个方格(1 ≤ M, N ≤ 30)。一些格子是坚固得令人惊讶的莲花,还有一些格子是岩石,其余的只是美丽、纯净、湛蓝的水。 
         贝西正在练习芭蕾舞,她站在一朵莲花上,想跳到另一朵莲花上去,她只能从一朵莲花跳到另一朵莲花上,既不能跳到水里,也不能跳到岩石上。

贝西的舞步很像象棋中的马步:每次总是先横向移动一格,再纵向移动两格,或先纵向移动两格,再横向移动一格。最多时,贝西会有八个移动方向可供选择。 同学们一直在观看贝西的芭蕾练习,发现她有时候不能跳到终点,因为中间缺了一些荷叶。于是他们想要添加几朵莲花来帮助贝西完成任务。同学们只想添加最少数量的莲花。当然,莲花不能放在石头上。 
         请确定必须要添加的莲花的最少数量。在添加莲花最少的基础上,确定贝西从起点跳到目标需要的最少步数。最后,确定满足添加的莲花数量最少时,步数最少的路径条数。

【输入格式】
     第一行:两个用空格分开的整数:M和N
     第二行到M + 1行:第i + 1行有N个用空格分开的整数,描述了池塘第i行的状态:0  为水,1  为莲花,2  为岩石,3  为YJC所在的起点,4  为贝西想去的终点。

【输出格式】
     第一行:一个整数:需要添加的莲花的最少数目;如果无解,则输出-1  
     第二行:一个整数:在添加莲花最少的基础上,YJC从起点跳到终点需要的最少步数;如果第一行是-1,不输出这行
     第三行:一个整数:在添加莲花最少的基础上,步数等于第二行输出的路径条数;如果第一行是-1,不输出这行
【样例】
4 8  
0 0 0 1 0 0 0 0  
0 0 0 0 0 2 0 1  
0 0 0 0 0 4 0 0  
3 0 0 0 0 0 1 0

2  
6  
2

【样例说明】
(最少要加两朵莲花,位置如  x  所示:
    0 0 0 1 0 0 0 0     0 0 0 1 0 0 0 0
    0 x 0 0 0 2 0 1     0 0 0 0 0 2 0 1
    0 0 0 0 x 4 0 0     0 0 x 0 x 4 0 0
    3 0 0 0 0 0 1 0     3 0 0 0 0 0 1 0
贝西至少要跳六步,两种不同的跳法如下:
    0 0 0 C 0 0 0 0     0 0 0 C 0 0 0 0
    0 B 0 0 0 2 0 F     0 0 0 0 0 2 0 F
    0 0 0 0 D G 0 0     0 0 B 0 D G 0 0
    A 0 0 0 0 0 E 0     A 0 0 0 0 0 E 0

【分析】:

令dist[x][y][z]表示(x,y)的最优莲花数位z,走了这么多步。用类似spfa的方法广搜:从起始点搜起,用spfa中的松弛操作<现在点的最优步数+1<到达点的步数,更新到达点的最优步数>优化,最后在终点的dist中找z的最小值且存在步数。再用这个dist数组从终点倒退回起点,用final[x][y][z]记录到(x,y)点有多少条莲花数为z的路,倒退条件当且仅当现在点的dist-1=到达点的dist,最后起点的final值即为路径数

【代码】:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
#define MAX 31
#define MAXN 901
#define IMAX 2147483647
struct point{int x,y,num;};
const int dx[]={1,1,-1,-1,2,2,-2,-2},dy[]={2,-2,2,-2,-1,1,-1,1};
int M,N,startx,starty,endx,endy;
int map[MAX][MAX],ansstep=IMAX,ansnum=IMAX;
int dist[MAX][MAX][MAXN];
long long final[MAX][MAX][MAXN],ansroad=0;
bool vis[MAX][MAX][MAXN];
void Q1()
{
queue<point> Q;
point use1;
for(int i=1;i<=M;i++)
for(int j=1;j<=N;j++)
for(int k=0;k<=N*M/2;k++)
dist[i][j][k]=IMAX;
use1.x=startx,use1.y=starty,use1.num=0;
Q.push(use1);
dist[use1.x][use1.y][0]=0;
while(!Q.empty())
{
point now=Q.front();
Q.pop();
for(int i=0;i<8;i++)
if(0<now.x+dx[i] && now.x+dx[i]<=M && 0<now.y+dy[i] && now.y+dy[i]<=N)
{
if(map[now.x+dx[i]][now.y+dy[i]]!=2 && dist[now.x][now.y][now.num]+1<dist[now.x+dx[i]][now.y+dy[i]][now.num+(map[now.x+dx[i]][now.y+dy[i]]==0 ? 1 : 0)])
{
dist[now.x+dx[i]][now.y+dy[i]][now.num+(map[now.x+dx[i]][now.y+dy[i]]==0 ? 1 : 0)]=dist[now.x][now.y][now.num]+1;
if(!vis[now.x+dx[i]][now.y+dy[i]][now.num+(map[now.x+dx[i]][now.y+dy[i]]==0 ? 1 : 0)])
{
point use;
vis[now.x+dx[i]][now.y+dy[i]][now.num+(map[now.x+dx[i]][now.y+dy[i]]==0 ? 1 : 0)]=true;
use.x=now.x+dx[i];
use.y=now.y+dy[i];
use.num=now.num+(map[now.x+dx[i]][now.y+dy[i]]==0 ? 1 : 0);
Q.push(use);
}
}
}
}
for(int i=0;i<=N*M/2;i++)
if(dist[endx][endy][i]!=IMAX)
{
ansnum=i;
ansstep=dist[endx][endy][i];
break;
}
}
void Q2()
{
queue<point> Q;
point use1;
memset(vis,false,sizeof(vis));
use1.x=endx,use1.y=endy,use1.num=ansnum;
Q.push(use1);
final[use1.x][use1.y][ansnum]=1;
while(!Q.empty())
{
point now=Q.front();
Q.pop();
if(!now.num && !map[now.x][now.y])   continue;
for(int i=0;i<8;i++)
if(0<now.x+dx[i] && now.x+dx[i]<=M && 0<now.y+dy[i] && now.y+dy[i]<=N)
{
if(map[now.x+dx[i]][now.y+dy[i]]!=2 && dist[now.x][now.y][now.num]-1==dist[now.x+dx[i]][now.y+dy[i]][now.num-(map[now.x][now.y]==0 ? 1 : 0)])
{
final[now.x+dx[i]][now.y+dy[i]][now.num-(map[now.x][now.y]==0 ? 1 : 0)]+=final[now.x][now.y][now.num];
if(!vis[now.x+dx[i]][now.y+dy[i]][now.num-(map[now.x][now.y]==0 ? 1 : 0)])
{
point use;
vis[now.x+dx[i]][now.y+dy[i]][now.num-(map[now.x][now.y]==0 ? 1 : 0)]=true;
use.x=now.x+dx[i];
use.y=now.y+dy[i];
use.num=now.num-(map[now.x][now.y]==0 ? 1 : 0);
Q.push(use);
}
}
}
}
ansroad=final[startx][starty][0];
}
int main()
{
freopen("silvlily.in","r",stdin);
freopen("silvlily.out","w",stdout);
scanf("%d%d",&M,&N);
for(int i=1;i<=M;i++)
for(int j=1;j<=N;j++)
{
scanf("%d",&map[i][j]);
if(map[i][j]==3)   startx=i,starty=j,map[i][j]=0;
if(map[i][j]==4)   endx=i,endy=j,map[i][j]=0;
}
Q1();
if(ansnum==IMAX)   {printf("-1\n");return 0;}
Q2();
printf("%d\n%d\n%lld\n",ansnum-1,ansstep,ansroad);
//system("pause");
return 0;
}

【官方题解】:

USACO FEB07 Problem 'silvlily' Analysis

by Richard Ho

We can treat this as a shortest path problem. At each square we keep track of how many lilypads we have to place to get there and how many jumps it took. We first want to minimize the lilypads and then minimize the jumps (moving onto a lilypad only takes one jump), while moving onto a blank square takes one lilypad + one jump.

We use BFS to update this information as we traverse the various routes. If a jump brings us to a square taking the same number of lilypads and jumps as it already says on the square, we can add the number of ways to that square. If we did better, we replace the number of ways to that square and add to queue. If we did worse, we don't update it. Below is code that matches this description.

【官方代码】:

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
FILE *in = fopen("silvlily.in", "r"), *out = fopen("silvlily.out", "w");
int m,n,d[50][50];
struct p {int x, y;};
class node
{
public:
int bestlily;
int bestjump;
long long nways;
node() {bestlily=-1; bestjump=-1; nways=0;}
};
node grid[50][50];
bool inq[50][50];
#define QSIZE 10000
p q[QSIZE];
int qstart,qend;
void enq(int x, int y)
{
if (!inq[x][y])
{
inq[x][y]=true;
q[qend].x=x;
q[qend].y=y;
qend++; qend%=QSIZE;
}
}
void updateq(int x, int y, int bl, int bj, long long pways)
{
if (grid[x][y].bestlily==-1 || bl<grid[x][y].bestlily)
{
grid[x][y].bestlily=bl;
grid[x][y].bestjump=bj;
grid[x][y].nways=pways;
enq(x,y); return;
}
if (grid[x][y].bestlily==bl && bj<grid[x][y].bestjump)
{
grid[x][y].bestlily=bl;
grid[x][y].bestjump=bj;
grid[x][y].nways=pways;
enq(x,y); return;
}
if (grid[x][y].bestlily==bl && bj==grid[x][y].bestjump)
{
grid[x][y].nways+=pways;
return;
}
}
int dirs[8][2]={{1,2},{2,1},{-1,2},{-2,1},{-1,-2},{-2,-1},{1,-2},{2,-1}};
void processqhead(void)
{
int x=q[qstart].x,y=q[qstart].y,nx,ny;
for (int i=0;i<8;i++)
{
nx=x+dirs[i][0];
ny=y+dirs[i][1];
if (nx>=0 && ny>=0 && nx<m && ny<n)
{
if (d[nx][ny]!=2)
updateq(nx,ny,grid[x][y].bestlily+(d[nx][ny]==1?0:1),grid[x][y].bestjump+1,grid[x][y].nways);
}
}
inq[x][y]=false;
qstart++; qstart%=QSIZE;
}
int main(void)
{
int i,j;
p a,b;
fscanf(in,"%i %i",&m,&n);
for (i=0;i<m;i++) for (j=0;j<n;j++) fscanf(in,"%i",&d[i][j]);
for (i=0;i<m;i++) for (j=0;j<n;j++)
{
if (d[i][j]==3) {d[i][j]=1; a.x=i;a.y=j;}
if (d[i][j]==4) {d[i][j]=1; b.x=i;b.y=j;}
inq[i][j]=false;
}
qstart=0; qend=0;
updateq(a.x,a.y,0,0,1);
while (qstart!=qend)
{
processqhead();
}
if (grid[b.x][b.y].bestlily==-1) fprintf(out,"-1\n");
else
fprintf(out,"%i\n%i\n%lld\n",grid[b.x][b.y].bestlily,grid[b.x][b.y].bestjump,grid[b.x][b.y].nways);
fclose(in); fclose(out); return 0;
}

转载注明出处:http://blog.csdn.net/u011400953

USACO CONTEST FEB07 白银莲花池 silvlily 分析相关推荐

  1. [USACO Feb07] 青铜莲花池

    169. [USACO Feb07] 青铜莲花池 ★   输入文件: bronlily.in   输出文件: bronlily.out    简单对比 时间限制:1 s   内存限制:128 MB 译 ...

  2. 【USACO】青铜莲花池[2]

    前言 搜索到这篇文章的朋友,那么很巧了,我们多半是一个学校的,为什么呢?因为这道题叫白银莲花池.. 题目 [问题描述] FJ建造了一个美丽的池塘,用于让奶牛们锻炼.这个长方形的池子被分割成了 M 行和 ...

  3. Flyerinternational外汇对黄金、白银、原油策略分析信息被多家公司“借用”

    Flyerinternational集团是一家全球知名的外汇经纪服务的公司,由于其盈利增长的优秀记录让flyerinternational 的核心业务成为全球外汇交易客户的首选,其他主要产品和服务也让 ...

  4. 故事公园-—昆明莲花池

    每个公园都有自己的地理特征,奇风异俗,各存其韵.昆明莲花池公园则因几处遗址以及涉及的故事,让人们留连往返,奕奕不舍,他(她)们的故事让世人感叹! 这里的遗址其中有南明末代皇帝的墓地,陈圆圆的梳妆楼,现 ...

  5. 1.5黄金白银最新行情走势分析预测,黄金实时操作建议

    黄金走势分析:      昨天金价至早盘冲高回落,至欧盘修正后未能冲破四小时的加速线,到七点出现弱空,美盘直接阴跌到1798一线,完全符合我们晚评的预期.      昨天下跌的主要原因,一是本身技术面 ...

  6. 萧乾升:4.20黄金白银TD最新走势分析后续布局

    4.20黄金走势分析操作建议: 昨日行情触及1790回落,实盘多空双获!遇阻回落正好是通道上沿,这个过程可以看做是对上周突破的双底颈线的回踩过程,给出颈线附近是很好的做多机会,回落就是给机会,陷入震荡 ...

  7. 正规现货白银中的技术分析是科学还是玄学?

    相信在正规现货白银投资平台中用技术分析进行交易的人不在少数,特别对于一些散户投资者来说,技术分析是他们的"谋生技能".但是在金融投资领域一直不乏反对的声音,说技术分析根本没有科学依 ...

  8. 蒋鑫鸿:9.8白银!沪银!期货白银!周四黄金价格走势分析及操作建议

    最新黄金行情走势分析 昨日黄金市场开盘在1702.1的位置后行情线延续前日倒锤头的回落压力下行,日线最低给到了1691的位置后行情强势拉升,日线最高触及到了1719.5的位置后行情整理,日线最终收线在 ...

  9. 萧乾升:4.14黄金,白银TD,纸白银,最新行情分析

    贵金属相关资讯: 周二(4月13日)亚洲时段,现货黄金持稳.周一(4月12日)金价下跌0.62%,因美债收益率小幅上涨,且美股不断创新高.另外,市场不断押注美国经济将大幅增长.不过,美国政府债务不断创 ...

  10. 11.11黄金原油价格趋势怎么看,黄金白银实时行情策略分析

    行情其实就像坐过山车,有高峰,也有低谷,这意味着,无论眼下是亏损是盈利或好是坏,都只是暂时的.又何必把一时赚赚亏亏看的那么重要!在这个过程中或多或少会有伤痕和不顺心的时候,但伤痕是过去,过去不等于现在 ...

最新文章

  1. VUE解决微信签名,SPA微信invalid signature问题,完美处理
  2. 4.10日一直报错application未注入的问题解决
  3. 自行车车把会吧车刮坏吗_花10分钟即可开始使用车把
  4. python怎么读出当前时间_Python读取Excel,日期列读出来是数字的处理
  5. PowerShell实战5: 批量增加AD组成员
  6. Android 四大组件学习之Activity二
  7. 408考研题错误之处
  8. (2)公众号开发-基础框架搭建
  9. dsp的ad标志位是什么_DSP简简单单学习之AD采样
  10. 小甲鱼学python学习笔记
  11. TensorFlow2.0-GPU加速
  12. 怎么批量把图片转文字?教你几招轻松完成
  13. 从零开始学习网络数据包分析:科来抓包的入门教程
  14. H.265/HEVC学习笔记:变换
  15. spark1.0和2.0的区别_Spark2.0 VS Spark 1.* -------SparkSession的区别
  16. 金海佳学C++primer 练习9.20
  17. Bugku之Flask_FileUpload
  18. Python+Vue计算机毕业设计在线考试系统yyn45(源码+程序+LW+部署)
  19. WEB网站类型系统中使用的OFFICE控件
  20. (阿里云 淘宝 百度 腾讯)到此一游

热门文章

  1. 前端开发: 微信小程序 (文字,链接)生成二维码
  2. OLTP和OLAP有何区别?
  3. Android Studio升级到3.5之后xml格式化问题
  4. 微信视频号视频怎么下载保存到手机相册?
  5. 免费的office软件哪个好用
  6. 阅读笔记0001之聊聊数据分析现状
  7. 【LeetCode】把数字翻译成字符串最长不含重复字符的子字符串
  8. 量化投资之工具篇一:Backtrader从入门到精通(6)-Indicator类源代码解读(1)
  9. 接入层-汇聚层组网设计配置案例——双归上行-负载
  10. docker运行rabbitmq