我感觉这是道不错的题目,我想了一天才写出来
主要是合法性的问题
其实就是考察多源最短路的算法,想了一天,考虑各种是否合法的情况,也加深了我对此算法的理解
首先,这题在dp的时候并不需要考虑合不合法,哈哈哈,我设的通过点k更新最短路。k代表的是已开放的村庄,若我们在i,j并不是都小于等于k时,照样dp就行了;当在第k个点时,我们有
dp[i][j][k]=min(dp[i][j][k],dp[i][k][k-1]+dp[k][j][k-1]),注意这时的dp[i][k][k-1]一定是合法的,因为k已开放,所以考虑dp的意义可知该情况合法。
总之,就是当前不成立的情况可能为后者所用,故只需要在输出答案的时候判断合法性即可
AC代码
#include <iostream>
#include <vector>
using namespace std;
typedef struct s
{
int to,val;
}s;
int country[205]={0};
int road[205][205]={0};
int dp[205][205][205]={0};
int main()
{
int n,m;scanf("%d%d",&n,&m);
for(int i=0;i<n;i++) scanf("%d",country+i);
for(int i=0;i<205;i++)
for(int j=0;j<205;j++)
for(int k=0;k<205;k++)
dp[i][j][k]=1e9;
for(int i=0;i<205;i++)
for(int j=0;j<205;j++)
{
road[i][j]=1e9;
if(i==j) road[i][j]=0;
}
for(int i=0;i<m;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
road[b][a]=min(road[b][a],c);
road[a][b]=min(road[a][b],c);
}
for(int k=0;k<n;k++)
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
{
if(k==0)
{
dp[i][j][k]=road[i][j];
dp[i][j][k]=min(dp[i][j][k],road[i][0]+road[0][j]);
continue;
}
dp[i][j][k]=dp[i][j][k-1];
dp[i][j][k]=min(dp[i][j][k],dp[i][k][k-1]+dp[k][j][k-1]);
}
int q;scanf("%d",&q);
while(q--)
{
int a,b,t;
scanf("%d%d%d",&a,&b,&t);
int u=max(a,b);
if(country[u]>t) printf("-1\n");
else
{
while(country[u]<=t&&u<n) u++;
u--;
if(dp[a][b][u]==1e9) printf("-1\n");
else printf("%d\n",dp[a][b][u]);
}
}
return 0;
}