另一道相似的floyd+dp题目: 博客戳这里 zoj 1232 哪道题可以瞬移很多次,好比这里的省去一个机票,想用floyd+dp的去戳←←...
因为这道题只去掉一个机票
所以并不一定要用dp+floyd.,只要加上条件松弛就可以省去dp了。
开两个数组分别存储路途总价格和路途最大机票价格即可用floyd
graph[i][j]:=存放i->j的总机费,并非答案
maxn[i][j]:=存在i->j路途最大的飞机票费用
答案为:graph[1][2]-maxn[1][2]
代码注释:
void floyd() //总的费用和最大机票价格分别存储即可省去DP
{
for(int k=1;k<num;k++)
for(int i=1;i<num;i++)
for(int j=1;j<num;j++)
{
int temp=graph[i][k]+graph[k][j]-max(maxn[i][k],maxn[k][j]); //i->k->j的总价格减去最大的机票价格(i->k,k->j)
if(temp<graph[i][j]-maxn[i][j]) //如果大于 i->j的总价格减去i->j最大的机票价格的费用,则松弛
{
graph[i][j]=graph[i][k]+graph[k][j]; //graph储存的是松弛后的i->j总的费用,并没有减钱。
maxn[i][j]=max(maxn[i][k],maxn[k][j]);//储存松弛后的 i->j的最大机票价格
}
}
}
floyd代码:
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <math.h>
#include <vector>
#include <cstdio>
#include <string>
#include<string.h>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
int graph[300][300],maxn[300][300];
int n,cost,num=3;
char ch1[100],ch2[100];
void init()
{
map<string,int>getid;
memset(maxn,0,sizeof(maxn));
for(int i=0;i<300;i++)
for(int j=0;j<300;j++)
graph[i][j]=10000000;
getid[ch1]=1;
getid[ch2]=2;
scanf("%d",&n);
while(n--)
{
scanf("%s %s %d",ch1,ch2,&cost);
if(getid[ch1]==0)
getid[ch1]=num++;
if(getid[ch2]==0)
getid[ch2]=num++;
graph[getid[ch1]][getid[ch2]]=cost;
maxn[getid[ch1]][getid[ch2]]=cost;
}
}
void floyd()
{
for(int k=1;k<num;k++)
for(int i=1;i<num;i++)
for(int j=1;j<num;j++)
{
int temp=graph[i][k]+graph[k][j]-max(maxn[i][k],maxn[k][j]);
if(temp<graph[i][j]-maxn[i][j])
{
graph[i][j]=graph[i][k]+graph[k][j];
maxn[i][j]=max(maxn[i][k],maxn[k][j]);
}
}
}
int main()
{
while(~scanf("%s\n%s",ch1,ch2)) //多组数据- - wa一次。
{
init();
floyd();
printf("%d\n",graph[1][2]-maxn[1][2]);
}
return 0;
}
spfa:也差不多是分别存储得出答案
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <math.h>
#include <vector>
#include <cstdio>
#include <string>
#include<string.h>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
int graph[300][300],maxn[300][300];
int n,cost,num=3;
char ch1[100],ch2[100];
void init()
{
map<string,int>getid;
memset(maxn,0,sizeof(maxn));
for(int i=0;i<300;i++)
for(int j=0;j<300;j++)
graph[i][j]=10000000;
getid[ch1]=1;
getid[ch2]=2;
scanf("%d",&n);
while(n--)
{
scanf("%s %s %d",ch1,ch2,&cost);
if(getid[ch1]==0)
getid[ch1]=num++;
if(getid[ch2]==0)
getid[ch2]=num++;
graph[getid[ch1]][getid[ch2]]=cost;
maxn[getid[ch1]][getid[ch2]]=cost;
}
}
void spfa()
{
bool vis[300];
int dist[300];
memset(vis,0,sizeof(vis));
for(int i=1;i<num;i++)
dist[i]=1000000;
vis[1]=1;
dist[1]=0;
queue<int>que;
que.push(1);
while(!que.empty())
{
int v=que.front(); //v为中间点,相当于floyd中的第一个循环k
que.pop();
vis[v]=0;
for(int i=1;i<num;i++)
if(dist[v]+graph[v][i]-max(maxn[1][v],maxn[v][i])<dist[i]-maxn[1][i])//dist[v]相当于上代码的graph[1][v].
{
dist[i]=dist[v]+graph[v][i]; //分别存储
maxn[1][i]=max(maxn[1][v],maxn[v][i]); //分别存储
if(!vis[i])
{
vis[i]=1;
que.push(i);
}
}
}
printf("%d\n",dist[2]-maxn[1][2]);
}
int main()
{
while(~scanf("%s\n%s",ch1,ch2))
{
init();
spfa();
}
return 0;
}