51nod 1459 迷宫游戏
BFS
bfs题目,要求最短路径下最大得分。
由于基础不扎实,我坑坑洼洼的打出了bfs求最短路径,代码如下:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <queue>
using namespace std;
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define N 510
int n,m,start,end;
int v[N],vis[N];
int g[N][N];
struct yuan
{
int value;
int dis;
int id;
};
void bfs_slove()
{
int ans_dis = 0,ans_val = 0;
queue<yuan> Q;
yuan now;
now.id = start;
now.value = now.dis = 0;
Q.push(now);
vis[now.id] = 1;
while(!Q.empty())
{
now = Q.front();
Q.pop();
for(int i = 0; i < n; i++)
{
if(vis[i] == 0 && g[now.id][i])
{
yuan next;
next.id = i;
next.dis = now.dis + g[now.id][i];
next.value = now.value + v[i];
if(next.id == end)
{
if(next.dis > ans_dis)
ans_dis = next.dis;
}
else
Q.push(next);
}
}
}
}
int main()
{
scanf("%d%d%d%d",&n,&m,&start,&end);
for(int i = 0; i < n; i++)
scanf("%d",&v[i]);
memset(g,0,sizeof(g));
memset(vis,0,sizeof(vis));
while(m--)
{
int a,b,dis;
scanf("%d%d%d",&a,&b,&dis);
g[a][b] = g[b][a] = dis;
}
bfs_slove();
return 0;
}
学习如何在,bfs求最短路径上,求最大得分呢?最开始我想先求出最大路径后,返回再计算比较最大得分记录。但是这样太麻烦,我们可以用优先队列来排好最优解。代码如下:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <queue>
using namespace std;
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define N 510
int n,m,start,end;
int v[N],vis[N];
int g[N][N];
struct yuan
{
int value;
int dis;
int id;
bool friend operator < (yuan a,yuan b)
{
if(a.dis == b.dis)
return a.value < b.value;
return a.dis > b.dis;
}
};
void bfs_slove()
{
priority_queue<yuan> Q;
yuan now;
now.id = start;
now.value = v[start];
now.dis = 0;
Q.push(now);
while(!Q.empty())
{
now = Q.top();
Q.pop();
vis[now.id] = 1;
if(now.id == end)
{
printf("%d %d\n",now.dis, now.value);
return ;
}
for(int i = 0; i < n; i++)
{
if(vis[i] == 0 && g[now.id][i])
{
yuan next;
next.id = i;
next.dis = now.dis + g[now.id][i];
next.value = now.value + v[i];
Q.push(next);
}
}
}
}
int main()
{
scanf("%d%d%d%d",&n,&m,&start,&end);
for(int i = 0; i < n; i++)
scanf("%d",&v[i]);
memset(g,0,sizeof(g));
memset(vis,0,sizeof(vis));
while(m--)
{
int a,b,dis;
scanf("%d%d%d",&a,&b,&dis);
g[a][b] = g[b][a] = dis;
}
bfs_slove();
return 0;
}
dijk
这题其实完全可以用迪杰斯特拉来计算最短路来做。
先随手打个dijk模板,代码如下
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <queue>
using namespace std;
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define N 510
int n,m,start,end;
int v[N],dis[N],vis[N];
int g[N][N];
void init()
{
for(int i = 0; i < n; i++)
{
for(int j = 0; j < n; j++)
{
if(i == j)
g[i][j] = 0;
else
g[i][j] = INF;
}
}
}
void MAP()
{
while(m--)
{
int a,b,dis;
scanf("%d%d%d",&a,&b,&dis);
if(dis < g[a][b])
g[a][b] = g[b][a] = dis;
}
}
void dijk()
{
for(int i = 0; i < n; i++)
dis[i] = INF;
memset(vis,0,sizeof(vis));
dis[start] = 0;
for(int i = 0; i < n; i++)
{
int MIN = INF;
int next;
for(int j = 0; j < n; j++)
{
if(!vis[j] && dis[j] < MIN)
{
MIN = dis[j];
next = j;
}
}
if(MIN == INF)
break;
vis[next] = 1;
for(int j = 0; j < n; j++)
{
if(!vis[j] && dis[j] > dis[next] + g[next][j])
dis[j] = dis[next] + g[next][j];
}
}
}
int main()
{
scanf("%d%d%d%d",&n,&m,&start,&end);
for(int i = 0; i < n; i++)
scanf("%d",&v[i]);
init();
MAP();
dijk();
printf("%d\n",dis[end]);
return 0;
}
现在我们需要再考虑最大得分,需要一个记录最大分值的数组,以及在路长相同时取最大得分。代码如下
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <queue>
using namespace std;
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define N 510
int n,m,start,end;
int v[N],dis[N],low[N],vis[N];
int g[N][N];
void init()
{
for(int i = 0; i < n; i++)
{
for(int j = 0; j < n; j++)
{
if(i == j)
g[i][j] = 0;
else
g[i][j] = INF;
}
}
}
void MAP()
{
while(m--)
{
int a,b,dis;
scanf("%d%d%d",&a,&b,&dis);
if(dis < g[a][b])
g[a][b] = g[b][a] = dis;
}
}
void dijk()
{
for(int i = 0; i < n; i++)
dis[i] = INF;
memset(vis,0,sizeof(vis));
memset(low,0,sizeof(low));
dis[start] = 0;
low[start] = v[start];
for(int i = 0; i < n; i++)
{
int MIN = INF;
int maxn = 0;
int next;
for(int j = 0; j < n; j++)
{
if(!vis[j] && dis[j] < MIN)
{
MIN = dis[j];
next = j;
maxn = low[j];
}
if(!vis[j] && dis[j] == MIN && maxn < low[j])
{
next = j;
maxn = low[j];
}
}
if(MIN == INF)
break;
vis[next] = 1;
for(int j = 0; j < n; j++)
{
if(!vis[j] && dis[j] > dis[next] + g[next][j])
{
dis[j] = dis[next] + g[next][j];
low[j] = low[next] + v[j];
}
if(!vis[j] && dis[j]==dis[next]+g[next][j] && low[j]<low[next]+v[j])
low[j] = low[next] + v[j];
}
}
}
int main()
{
scanf("%d%d%d%d",&n,&m,&start,&end);
for(int i = 0; i < n; i++)
scanf("%d",&v[i]);
init();
MAP();
dijk();
printf("%d %d\n",dis[end],low[end]);
return 0;
}