這題有這麼一個思路:
將每個
然後對於每個
從
最後再造兩個點
一個點向所有的點
另一個由所有的點
最後跑一邊
代碼如下:
#include<bits/stdc++.h>
using namespace std;
#define M 55
#define ll long long
const ll oo=1e13;
void Min(ll &a,ll b){
if(a>b)a=b;
}
char str[M];
int ok[M][M],val[M];
int dis[M][M][M][M];
struct node{
int i,a;ll len;
bool operator <(const node &A)const{
return len>A.len;
}
};
priority_queue<node>Q;
ll mark[M][M];int T[M][M];
int n;
ll Dijkstra(){//dp
Q.push((node){0,0,0});
while(!Q.empty()){
node tmp=Q.top();Q.pop();
if(tmp.i==n+1&&tmp.a==n+1)return tmp.len;
if(T[tmp.i][tmp.a])continue;
T[tmp.i][tmp.a]=1;
for(int j=1;j<=n;j++)
for(int b=1;b<=n;b++){
ll len=tmp.len+dis[tmp.i][tmp.a][j][b];
if(~dis[tmp.i][tmp.a][j][b]&&mark[j][b]>len){
mark[j][b]=len;
Q.push((node){j,b,len});
}
}
ll len=tmp.len+dis[tmp.i][tmp.a][n+1][n+1];
if(~dis[tmp.i][tmp.a][n+1][n+1]&&mark[n+1][n+1]>len)
Q.push((node){n+1,n+1,tmp.len+dis[tmp.i][tmp.a][n+1][n+1]});
}
return -1;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%s",str+1);
for(int j=1;j<=n;j++)
if(str[j]=='Y')ok[i][j]=1;
}
for(int i=1;i<=n;i++)
scanf("%d",&val[i]);
for(int i=0;i<=n+1;i++)
for(int j=0;j<=n+1;j++)
mark[i][j]=oo;
memset(dis,-1,sizeof(dis));
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
for(int a=1;a<=n;a++)
for(int b=1;b<=n;b++)
if(ok[i][j]&&val[a]>=val[b])dis[i][a][j][b]=abs(val[j]-val[b]);
for(int i=1;i<=n;i++){
dis[0][0][1][i]=dis[1][i][0][0]=abs(val[i]-val[1]);
dis[n+1][n+1][n][i]=dis[n][i][n+1][n+1]=0;
}
//預處理
cout<<Dijkstra()<<endl;
return 0;
}