Solution - P3659

\(\color{3498DB}\text{P3659 [USACO17FEB] Why Did the Cow Cross the Road I G}\)

对于每个位置枚举周围走三步能到的点(设为 \((i,j)\)),进行连边(单向边,当前位置连向 \((i,j)\)),边权为 \(3T+a_{i,j}\)

然后跑最短路即可。

答案为 \(\min\{ dis_{(n,n)}, dis_{(n,n-1)}+T, dis_{(n-1,n)}+T, dis_{(n-1,n-1)}+2T, dis_{(n,n-2)}+2T, dis_{(n-2,n)}+2T\}\)

时间复杂度 \(O(n^2 \log n^2)\)

#include<cstdio>
#include<cstring>
#include<queue>
typedef long long LL;
typedef std::pair<LL,int> PLI;
const int N=110;
const int cx[16]={-2,-1,1,2,2,1,-1,-2,0,1,0,-1,0,3,0,-3},cy[16]={1,2,2,1,-1,-2,-2,-1,1,0,-1,0,3,0,-3,0};
int n,T;
int a[N][N];
LL dis[N*N];
bool vis[N*N];
int head[N*N],tot;
struct Edge{
	int to,val,nxt;
}e[N*N<<5];
std::priority_queue<PLI,std::vector<PLI>,std::greater<PLI> > q;
inline int read(){
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9')ch=='-'?f=0:0,ch=getchar();
	while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
	return f?x:-x;
}
inline LL min(LL a,LL b){return a<b?a:b;}
inline void add(int u,int v,int w){e[++tot]=(Edge){v,w,head[u]},head[u]=tot;}
inline int f(int x,int y){return (x-1)*n+y;}
inline void push(int x,int y){
	for(int i=0,_x,_y;i<16;++i){
		_x=x+cx[i],_y=y+cy[i];
		if(1<=_x&&_x<=n&&1<=_y&&_y<=n)
			add(f(x,y),f(_x,_y),a[_x][_y]+3*T);
	}
}
inline void Dijkstra(){
	memset(dis,0x3f3f,sizeof(dis)),dis[1]=0,q.push(PLI(0,1));
	int u;
	while(!q.empty()){
		u=q.top().second,q.pop();
		if(vis[u])continue;
		vis[u]=1;
		for(int i=head[u],v;i;i=e[i].nxt)if(!vis[v=e[i].to]&&dis[v]>dis[u]+e[i].val)
			q.push(PLI(dis[v]=dis[u]+e[i].val,v));
	}
}
int main(){
	n=read(),T=read();
	for(int i=1;i<=n;++i)for(int j=1;j<=n;++j)
		a[i][j]=read();
	for(int i=1;i<=n;++i)for(int j=1;j<=n;++j)
		push(i,j);
	Dijkstra();
	printf("%lld\n",min(min(dis[f(n,n)],dis[f(n,n-1)]+T),min(min(dis[f(n-1,n)]+T,dis[f(n-1,n-1)]+(T<<1)),min(dis[f(n-2,n)]+(T<<1),dis[f(n,n-2)]+(T<<1)))));
	return 0;
}
posted @ 2023-12-18 18:18  L01001101  阅读(20)  评论(0)    收藏  举报