白银莲花池
(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. POJ 3686 The Windy's
  2. Boost库之circular_buffer
  3. Matlab 非线性规划问题模型代码
  4. soapui 测试soap_使用SoapUI调用不同的安全WCF SOAP服务-基本身份验证,第二部分
  5. eventsource前台怎么接收一个对象数据_Java开发经验总结篇(1)——数据保存的整洁方法...
  6. 权限管理系统之用户管理
  7. 事务例子_图文详解:数据库事务与锁
  8. 没业绩怎么写好年终总结?这样写总结年终奖翻倍!
  9. ssis配置文件优先级_SSIS优先约束概述
  10. Python 源码剖析(二)—— 第一次修改 Python 源代码
  11. python爬虫怎么挣钱-月薪45K的Python爬虫工程师告诉你爬虫应该怎么学,太详细了!...
  12. UILabel实现自适应宽高需要注意的地方(三)
  13. 《寒江独钓》的作者教您如何高效阅读本书
  14. 【推荐】微信运营书一箩筐,微信运营手册、微信力量
  15. linux monitor工具,5 款 Ubuntu 系统监控工具
  16. 图片转字符画(已打包)
  17. XOP 网格计划是什么?XOP 的特性
  18. java 甘特图_甘特图(Gantt chart)深度解析
  19. 目标检测 YOLOv5 - 卷积层和BN层的融合
  20. Open vSwitch详解

热门文章

  1. 融合云信平台对接_java代码
  2. Linux内核基础--事件通知链(notifier chain)good【转】
  3. 5G时代的一个杀手级应用,可能是“云上电脑”?
  4. 公民委托诉讼代理人的注意事项
  5. 打造健康的程序员-饮食篇
  6. SCAR:Scalable Consensus Algorithm 一种可伸缩共识算法
  7. linux cp指令报错:cp: -r not specified; cp: omitting directory ‘xxx‘(需要加-r递归拷贝)
  8. iOS 5 故事板进阶(4)
  9. 微信开发--IOS微信端confirm以及alert去掉网址的方法
  10. A fastandrobust convolutionalneuralnetwork-based defect detection model inproductqualitycontrol-阅读笔记