题意:在迷宫中,王子Y想要到达公主C的位置,迷宫中有障碍#,收费站*,传送点P。对于收费站,输入给出所收费用cost;对于传送点,可以选择传送到任意其他的传送点,或者不传送。要求让路径花费最小,输出最小花费。
思路:最短路径或者BFS。对于传送点P,由于可以任意互相到达,于是可以将所有传送点合为一个点。对于每个点,向四个方向连边,对边加权值cost或者0。构图之后直接SPFA。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int M=5001;
const int INF=5000000;
int r,c,w,sum,cnt,cost;
int a[M][M],pre[M],mark[M],dist[M];
char ch[M][M];
struct node
{
int v,w,next;
}edge[M*M];
void work_init()
{
cnt=0;
memset(pre,-1,sizeof(pre));
}
void work_addedge(int u,int v,int w)
{
edge[cnt].v=v;
edge[cnt].w=w;
edge[cnt].next=pre[u];
pre[u]=cnt++;
}
void work_spfa(int s)
{
int v,w,now;
queue <int> q;
for(int i=0;i<M;i++)
{
mark[i]=false;
dist[i]=INF;
}
q.push(s);
mark[s]=true;
dist[s]=0;
while(!q.empty())
{
now=q.front();
q.pop();
mark[now]=false;
for(int i=pre[now];i>-1;i=edge[i].next)
{
v=edge[i].v;
w=edge[i].w;
if(dist[now]+w<dist[v])
{
dist[v]=dist[now]+w;
if(!mark[v])
{
mark[v]=true;
q.push(v);
}
}
}
}
}
void work_makegraph()
{
sum=4;
for(int i=1;i<=r;i++)
for(int j=1;j<=c;j++)
{
if(ch[i][j]=='Y')
a[i][j]=1;
if(ch[i][j]=='C')
a[i][j]=2;
if(ch[i][j]=='P')
a[i][j]=3;
if(ch[i][j]=='*')
a[i][j]=sum++;
}
for(int i=1;i<=r;i++)
for(int j=1;j<=c;j++)
if(ch[i][j]!='#')
{
if(i>1 && ch[i-1][j]!='#')
{
if(ch[i-1][j]=='*') w=cost;
else w=0;
work_addedge(a[i][j],a[i-1][j],w);
}
if(i<r && ch[i+1][j]!='#')
{
if(ch[i+1][j]=='*') w=cost;
else w=0;
work_addedge(a[i][j],a[i+1][j],w);
}
if(j>1 && ch[i][j-1]!='#')
{
if(ch[i][j-1]=='*') w=cost;
else w=0;
work_addedge(a[i][j],a[i][j-1],w);
}
if(j<c && ch[i][j+1]!='#')
{
if(ch[i][j+1]=='*') w=cost;
else w=0;
work_addedge(a[i][j],a[i][j+1],w);
}
}
}
int main()
{
while(cin>>r>>c>>cost)
{
for(int i=1;i<=r;i++)
for(int j=1;j<=c;j++)
cin>>ch[i][j];
work_init();
work_makegraph();
work_spfa(1);
if(dist[2]<INF) cout<<dist[2]<<endl;
else cout<<"Damn teoy!"<<endl;
}
return 0;
}