bzoj2143 飞飞侠 最短路

       用d[i][j][k]表示走到第(i,j)格,在不弹射的情况下还能再走k步的最小花费,那么有转移:

       d[i][j][k]->d[x][y][k-1],其中(i,j)和(x,y)相邻或相等,k>0,表示走到相邻一格或不走;

       d[i][j][0]+a[i][j]->d[x][y][b[i][j]],表示一次弹射。

       注意样例输入的A,B数组相反?另外听说卡spfa?

AC代码如下:

#include
#include
#include
#include
#include
#define N 155
#define inf 1000000000
using namespace std;

const int dx[4]={-1,1,0,0},dy[4]={0,0,-1,1};
int m,n,len,x1,x2,x3,y1,y2,y3,t1,t2,t3,a[N][N],b[N][N],d[N][N][N<<1];
bool vis[N][N][N<<1];
struct node{ int x,y,z,d; };
priority_queue q;
bool operator <(node u,node v){ return u.d>v.d; }
void solve(int sx,int sy){
	int i,j,k; while (!q.empty()) q.pop();
	for (i=1; i<=m; i++)
		for (j=1; j<=n; j++)
			for (k=0; k<=len; k++){
				vis[i][j][k]=0; d[i][j][k]=inf;
			}
	d[sx][sy][0]=0;
	node u,v; u.x=sx; u.y=sy; u.z=u.d=0; q.push(u);
	while (!q.empty() && !(vis[x1][y1][0] && vis[x2][y2][0] && vis[x3][y3][0])){
		u=q.top(); q.pop();
		if (vis[u.x][u.y][u.z]) continue; vis[u.x][u.y][u.z]=1;
		if (u.z){
			for (k=0; k<4; k++){
				i=u.x+dx[k]; j=u.y+dy[k];
				if (i>0 && i<=m && j>0 && j<=n && u.d


by lych

2016.3.4

你可能感兴趣的:(bzoj)