bzoj2143: 飞飞侠
表示自己dij写挫了QWQ
直接建边肯定是很不可做的,那么考虑转换一下,假如我在这里选择跳,相当于可以走a[i][j]步
三次dij
这样转移是150^3次方,强行算完是会T的,那么其实找到了那两个位置就够了
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> #include<queue> using namespace std; typedef long long LL; const int dx[5]={-1,0,1,0,0}; const int dy[5]={0,1,0,-1,0}; int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int n,m; int b[210][210],X[3],Y[3]; LL a[210][210],cost[3]; struct dij { int x,y,z;LL k; dij(){} dij(int X,int Y,int Z,LL K){x=X,y=Y,z=Z,k=K;} friend bool operator>(dij d1,dij d2){return d1.k>d2.k;} friend bool operator<(dij d1,dij d2){return d1.k<d2.k;} };priority_queue<dij,vector<dij>,greater<dij> >q; LL d[210][210][310]; bool v[210][210][310]; void dijkstra(int w) { memset(d,63,sizeof(d));d[X[w]][Y[w]][0]=0; memset(v,false,sizeof(v)); q.push(dij(X[w],Y[w],0,d[X[w]][Y[w]][0])); while(!q.empty()&&(!v[X[0]][Y[0]][0]||!v[X[1]][Y[1]][0]||!v[X[2]][Y[2]][0])) { dij tno=q.top();q.pop(); int x=tno.x,y=tno.y,z=tno.z; if(v[x][y][z]==true)continue; v[x][y][z]=true; if(z>0) { for(int k=0;k<=4;k++) { int tx=x+dx[k],ty=y+dy[k]; if(0<tx&&tx<=n&&0<ty&&ty<=m) { if(d[tx][ty][z-1]>d[x][y][z]) { d[tx][ty][z-1]=d[x][y][z]; q.push(dij(tx,ty,z-1,d[tx][ty][z-1])); } } } } else { if(d[x][y][b[x][y]]>d[x][y][z]+a[x][y]) { d[x][y][b[x][y]]=d[x][y][z]+a[x][y]; q.push(dij(x,y,b[x][y],d[x][y][b[x][y]])); } } } while(!q.empty())q.pop(); for(int i=0;i<=2;i++) { if(d[X[i]][Y[i]][0]==d[0][0][0])cost[i]=-1; if(cost[i]!=-1)cost[i]+=d[X[i]][Y[i]][0]; } } int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); n=read(),m=read(); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) b[i][j]=read(),b[i][j]=min(b[i][j],300); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) a[i][j]=read(); for(int i=0;i<=2;i++) X[i]=read(),Y[i]=read(); memset(cost,0,sizeof(cost)); for(int i=0;i<=2;i++)dijkstra(i); if(cost[0]==-1&&cost[1]==-1&&cost[2]==-1)printf("NO\n"); else { for(int i=0;i<=2;i++) if(cost[i]==-1)cost[i]=(1LL<<62); if(cost[0]<=cost[1]&&cost[0]<=cost[2])printf("X\n%lld\n",cost[0]); else if(cost[1]<=cost[0]&&cost[1]<=cost[2])printf("Y\n%lld\n",cost[1]); else if(cost[2]<=cost[0]&&cost[2]<=cost[1])printf("Z\n%lld\n",cost[2]); } return 0; }
pain and happy in the cruel world.