【HDNOIP】HD201404最短路径
HD201404最短路径
【试题描述】
a、b、c是3个互不相等的1位正数,用它们和数字0可以填满一个n行n列的方格阵列,每格中都有4种数码中的一个。填入0的格子表示障碍物,不能属于任何路径。你是否能找出一条从1行1列出发,到达n行n列且代价最小的路径呢?注意:每一格只能走向与之相邻的上、下、左、右的非0且不出界的格子。而所谓路径代价指的是路径经过的所有格子中的数字总和。请你编程求出从1行1列的位置出发到达n行n列的最小路径代价,若无法到达就输出-1。
【输入要求】
第一行输入数字n。
接下来的n行每行是一个长度为n的数字串,这n个字符串就构成了一个数字符的方阵。方阵中除了'0'外,最多还可以包含3种数字符。
【输出要求】
【输入实例】
【输入样例1】
4
1231
2003
1002
1113
【输入样例2】
4
3150
1153
3311
0530
【输出实例】
【输出样例1】
10
【输出样例2】
-1
【其他说明】
60%的数据,n<10,80%的数据,n<100,100%的数据,n<1000
【试题分析】
第一眼:这不就是迷宫吗!?看我秒过!!
第二眼:还不太一样,迷宫是走一步ans++,这个是要加一个变量的
第三眼:上DFS代码吧!!
于是就花了1小时yy了这么一个代码:
#include<iostream>
#include<cstring>
using namespace std;
char map[1001][1001],cinm[1001][1001];
int a[1001][1001],ans=0,m,n,k[1001][1001],k1[1001][1001],mk=0;//k不变,变的只是k1.
void res(int u,int v,int i,int j)
{
int t=k1[u][v];
if(u==i&&v==j) ans=t,mk=1;
if(v<m-1&&map[u][v+1]!='#'&&a[u][v+1]>t+k[u][v+1])
{
k1[u][v+1]=k[u][v+1]+t;
a[u][v+1]=k1[u][v+1];
res(u,v+1,i,j);
}
if(u>0&&map[u-1][v]!='#'&&a[u-1][v]>t+k[u-1][v])
{
k1[u-1][v]=k[u-1][v]+t;
a[u-1][v]=k1[u-1][v];
res(u-1,v,i,j);
}
if(v>0&&map[u][v-1]!='#'&&a[u][v-1]>t+k[u][v-1])
{
k1[u][v-1]=k[u][v-1]+t;
a[u][v-1]=k1[u][v-1];
res(u,v-1,i,j);
}
if(u<n-1&&map[u+1][v]!='#'&&a[u+1][v]>t+k[u+1][v])
{
k1[u+1][v]=k[u+1][v]+t;
a[u+1][v]=k1[u+1][v];
res(u+1,v,i,j);
}
}
int main()
{
cin>>n;
m=n;
for(int i=0;i<n;i++)
{
cin>>cinm[i];
for(int j=0;j<n;j++)
{
k[i][j]=cinm[i][j]-'0';
k1[i][j]=k[i][j];
}
}
int startx=0,starty=0,endx=n-1,endy=n-1;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
{
if(i==startx&&j==starty) map[i][j]='S';
else if(i==endx&&j==endy) map[i][j]='T';
if(k[i][j]==0)map[i][j]='#';
else map[i][j]='.';
}
memset(a,1,sizeof(a));
a[0][0]=0;
res(startx,starty,endx,endy);
if(mk==1)cout<<ans<<endl;
else cout<<-1;
}
结果没有看数据范围,1000!!?
结果对了,但是就是时间超了。
细细想来也没有神马办法优化,罢罢罢……
BFS:
好了,如果DFS时间超限,那么只能用BFS了。
于是又yy了一个BFS的代码:
#include<iostream>
using namespace std;
char Graph[1001][1001];
int n,m,startx,starty;
int Dir[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
int Vis[1001][1001];
int Dis[1001][1001];
char cinm[1001][1001],k[1001][1001];
int Fit(int x,int y)
{
return (x>=1&&x<=n&&y>=1&&y<=m);
}
int BFS(int x,int y)
{
int queue[100000];
int i,head=0,tail=0;
queue[tail++]=x;
queue[tail++]=y;
Vis[x][y]=1;
while(head<tail)
{
int nowx=queue[head++];
int nowy=queue[head++];
for(i=0;i<4;i++)
{
int tmpx=nowx+Dir[i][0];
int tmpy=nowy+Dir[i][1];
if(Fit(tmpx,tmpy)&&tmpx==n&&tmpy==n&&Graph[tmpx][tmpy]=='.') return Dis[nowx][nowy]+k[tmpx][tmpy];
if(Fit(tmpx,tmpy)&&Graph[tmpx][tmpy]=='.'&&Dis[nowx][nowy]+k[tmpx][tmpy]<Dis[tmpx][tmpy])
{
Dis[tmpx][tmpy]=Dis[nowx][nowy]+k[tmpx][tmpy];
queue[tail++]=tmpx;
queue[tail++]=tmpy;
}
}
}
return 0;
}
int main()
{
int i ,j ,startx=1,starty=1;
scanf("%d",&n);
m=n;
for(int i=1;i<=n;i++)
{
scanf("%s",cinm[i]+1);
for(int j=1;j<=n;j++)
k[i][j]=cinm[i][j]-'0',Dis[i][j]=999999;
}
Dis[1][1]=k[1][1];
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
if(k[i][j]==0)Graph[i][j]='#';
else Graph[i][j]='.';
}
int ans=0;
ans=BFS(startx,starty);
if(ans!=0) printf("%d\n",ans);
else printf("-1\n");
}
/*
7
3221000
3110012
3123031
1123301
2211123
0012333
3312001*/
结果错误。
有些点的确能A,但是有些点死活A不了。
突然发现了这样一个条件:最多有三个除0之外不同的数,于是又yy了一个三个队列维护的代码:
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
inline int read() {
int x=0,f=1;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=getchar()) x=x*10+c-'0';
return x*f;
}
char cinm[1001][1001];
int n,Dis[1001][1001],Vis[1001][1001],number[1001],timek,k[1001][1001];
struct P
{
int x,y;
bool operator < (const P& ths) {return Dis[x][y]<Dis[ths.x][ths.y];}
};
queue<P> que[3];
int getfront()
{
int c=-1;
if(que[0].size()) c=0;
if(que[1].size()&&(c<0||que[1].front()<que[c].front())) c=1;
if(que[2].size()&&(c<0||que[2].front()<que[c].front())) c=2;
return c;
}
int Fit(int x,int y)
{
return (x>=1&&x<=n&&y>=1&&y<=n);
}
int Dir[4][2]={{1,0},{0,1},{-1,0},{0,-1}};//方向数组
int BFS()
{
if(k[1][1]==0||k[n][n]==0) return -1;
que[number[cinm[1][1]]].push((P){1,1});
Dis[1][1]=k[1][1];
while(que[0].size()+que[1].size()+que[2].size())//当三个队列的大小和非空时
{
int t=getfront();
int x=que[t].front().x;
int y=que[t].front().y;//获取坐标
que[t].pop();
if(x==n&&y==n) return Dis[x][y];
if(Vis[x][y]==1) continue;
Vis[x][y]=1;
for(int i=0;i<=3;i++)
{
int nx=x+Dir[i][0];
int ny=y+Dir[i][1];
if(Fit(nx,ny)&&k[nx][ny]!=0&&Dis[x][y]+k[nx][ny]<Dis[nx][ny])
{
Dis[nx][ny]=Dis[x][y]+k[nx][ny];
que[number[cinm[nx][ny]]].push((P){nx,ny});
}
}
}
return -1;
}
int main()
{
n=read();
for(int i=1;i<=n;i++) scanf("%s",cinm[i]+1);
memset(number,-1,sizeof(number));
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
if(number[cinm[i][j]]<0&&cinm[i][j]!='0') number[cinm[i][j]]=timek++;//为非0元素标号
Dis[i][j]=99999999;
k[i][j]=cinm[i][j]-'0';
}
printf("%d\n",BFS());
}
【代码】
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
inline int read() {
int x=0,f=1;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=getchar()) x=x*10+c-'0';
return x*f;
}
char cinm[1001][1001];
int n,Dis[1001][1001],Vis[1001][1001],number[1001],timek,k[1001][1001];
struct P
{
int x,y;
bool operator < (const P& ths) {return Dis[x][y]<Dis[ths.x][ths.y];}
};
queue<P> que[3];
int getfront()
{
int c=-1;
if(que[0].size()) c=0;
if(que[1].size()&&(c<0||que[1].front()<que[c].front())) c=1;
if(que[2].size()&&(c<0||que[2].front()<que[c].front())) c=2;
return c;
}
int Fit(int x,int y)
{
return (x>=1&&x<=n&&y>=1&&y<=n);
}
int Dir[4][2]={{1,0},{0,1},{-1,0},{0,-1}};//方向数组
int BFS()
{
if(k[1][1]==0||k[n][n]==0) return -1;
que[number[cinm[1][1]]].push((P){1,1});
Dis[1][1]=k[1][1];
while(que[0].size()+que[1].size()+que[2].size())//当三个队列的大小和非空时
{
int t=getfront();
int x=que[t].front().x;
int y=que[t].front().y;//获取坐标
que[t].pop();
if(x==n&&y==n) return Dis[x][y];
if(Vis[x][y]==1) continue;
Vis[x][y]=1;
for(int i=0;i<=3;i++)
{
int nx=x+Dir[i][0];
int ny=y+Dir[i][1];
if(Fit(nx,ny)&&k[nx][ny]!=0&&Dis[x][y]+k[nx][ny]<Dis[nx][ny])
{
Dis[nx][ny]=Dis[x][y]+k[nx][ny];
que[number[cinm[nx][ny]]].push((P){nx,ny});
}
}
}
return -1;
}
int main()
{
n=read();
for(int i=1;i<=n;i++) scanf("%s",cinm[i]+1);
memset(number,-1,sizeof(number));
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
if(number[cinm[i][j]]<0&&cinm[i][j]!='0') number[cinm[i][j]]=timek++;//为非0元素标号
Dis[i][j]=99999999;
k[i][j]=cinm[i][j]-'0';
}
printf("%d\n",BFS());
}
【HDNOIP】HD201404最短路径的更多相关文章
- Johnson 全源最短路径算法
解决单源最短路径问题(Single Source Shortest Paths Problem)的算法包括: Dijkstra 单源最短路径算法:时间复杂度为 O(E + VlogV),要求权值非负: ...
- Floyd-Warshall 全源最短路径算法
Floyd-Warshall 算法采用动态规划方案来解决在一个有向图 G = (V, E) 上每对顶点间的最短路径问题,即全源最短路径问题(All-Pairs Shortest Paths Probl ...
- Dijkstra 单源最短路径算法
Dijkstra 算法是一种用于计算带权有向图中单源最短路径(SSSP:Single-Source Shortest Path)的算法,由计算机科学家 Edsger Dijkstra 于 1956 年 ...
- Bellman-Ford 单源最短路径算法
Bellman-Ford 算法是一种用于计算带权有向图中单源最短路径(SSSP:Single-Source Shortest Path)的算法.该算法由 Richard Bellman 和 Leste ...
- 最短路径算法-Dijkstra
Dijkstra是解决单源最短路径的一般方法,属于一种贪婪算法. 所谓单源最短路径是指在一个赋权有向图中,从某一点出发,到另一点的最短路径. 以python代码为例,实现Dijkstra算法 1.数据 ...
- bzoj 4016: [FJOI2014]最短路径树问题
bzoj4016 最短路路径问题 Time Limit: 5 Sec Memory Limit: 512 MB Description 给一个包含n个点,m条边的无向连通图.从顶点1出发,往其余所有点 ...
- 51nod 1459 迷宫游戏 (最短路径—Dijkstra算法)
题目链接 中文题,迪杰斯特拉最短路径算法模板题. #include<stdio.h> #include<string.h> #define INF 0x3f3f3f3f ],v ...
- C++迪杰斯特拉算法求最短路径
一:算法历史 迪杰斯特拉算法是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法.是从一个顶点到其余各顶点的最短路径算法,解决的是有向图中最短路径问题.迪杰斯特拉算法主要特点是以 ...
- 求两点之间最短路径-Dijkstra算法
Dijkstra算法 1.定义概览 Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.D ...
随机推荐
- 《Maven实战》阅读笔记
java -versionmvn -vmvn help:system m2eclipse maven->install MAVEN_OPTS: -Xms128m -Xmx512mmvn clea ...
- LeetCode One Edit Distance
原题链接在这里:https://leetcode.com/problems/one-edit-distance/ Given two strings S and T, determine if the ...
- route命令(转)
Linux系统的route命令用于显示和操作IP路由表(show / manipulate the IP routing table).要实现两个不同的子网之间的通信,需要一台连接两个网络的路由器,或 ...
- 第八篇 SQL Server安全数据加密
本篇文章是SQL Server安全系列的第八篇,详细内容请参考原文. Relational databases are used in an amazing variety of applicatio ...
- python_列表
1. 列表的定义 (1) 用[]包含的元素,就是列表 (2)可以用list函数定义列表 2. 基本的列表操作(可参考示例) (1)元素赋值 (2)删除元素 (3)分片赋值 3. 列表方法 (1) ...
- MongoDB是?
MongoDB是? MongoDB是一个基于分布式文件存储的数据库 由C++编写 旨在为 WEB 应用提供可扩展的高性能数据存储解决方案 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当 ...
- WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform
参看:http://www.secdoctor.com/html/yyjs/31101.html
- 解决:Detected memory leaks
最近在一个项目中,程序退出后都出现内存泄漏: Detected memory leaks!Dumping objects ->{171} normal block at 0x05785AD0, ...
- 解决:AppMsg - Warning: calling DestroyWindow in CWnd::~CWnd; OnDestroy or PostNcDestroy in derived class will not be called
类似的还有:AppMsg - Warning: Destroying non-NULL m_pMainWnd(这是因为你既没有自己delete,也没有调用DestroyWindow) 首先解决第一个, ...
- java对象占多少内存
通常来说Hotspot jvm的对内存中的对象由以下几个部分组成 一个对象头,包含了一些整理工作所需信息 原始类型字段,不同类型大小各异(表1) 引用字段,占据4个字节(byte) 填充,在对象的末尾 ...