TYVJ-1106 SPFA

不知道为什么这个题被分到了DP分类==|

我最近感到SPFA在处理网格最短路之类的问题很方便!

对于这道题,我开始想DP,后来想到SPFA,就用SPFA,貌似要比DP简单。这是个最优化问题。

/*
 * tyvj-1106
 * mike-w
 * 2012-10-30
 *
 */
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#define MAXN 1111
#define QSIZE 111111
#define xLOL_DEBUG

int s[MAXN][MAXN];
int N;
int que[QSIZE][2], qhead, qtail, qlen;
int inq[MAXN][MAXN];
int dst[MAXN][MAXN];

int enque(int x, int y)
{
	if(qlen==QSIZE)
		puts("queue is full!");
	que[qtail][0]=x;
	que[qtail][1]=y;
	qtail++;
	if(qtail==QSIZE)
		qtail=0;
	qlen++;
	return 0;
}

int deque(int *x, int *y)
{
	if(qlen==0)
		puts("queue is empty!");
	*x=que[qhead][0];
	*y=que[qhead][1];
	qhead++;
	if(qhead==QSIZE)
		qhead=0;
	qlen--;
	return 0;
}

int relax(int xa, int ya, int xb, int yb)
{
	if(!dst[xb][yb] || dst[xa][ya]+s[xb][yb]<dst[xb][yb])
	{
		dst[xb][yb]=dst[xa][ya]+s[xb][yb];
		if(!inq[xb][yb])
			enque(xb, yb), inq[xb][yb]=1;
	}
	return 0;
}

#ifdef LOL_DEBUG
int disp_dst(void)
{
	int i, j;
	for(i=1; i<=N; i++)
		for(j=1; j<=i; j++)
			printf("%2d%c", dst[i][j], j==i?'\n':' ');
	return 0;
}
#endif

int spfa(int xo, int yo)
{
	int xa, ya, xb, yb;

	qhead=qtail=qlen=0;
	enque(xo, yo);
	inq[xo][yo]=1;
	dst[xo][yo]=s[xo][yo];
	while(qlen>0)
	{
		deque(&xa, &ya);
#ifdef LOL_DEBUG
		printf("%d,%d is poped\n", xa, ya);
		disp_dst();
		getchar();
#endif
		inq[xa][ya]=0;
		/* move right */
		xb=xa;
		yb=ya+1;
		if(yb==xb+1)
			yb=1;
		relax(xa, ya, xb, yb);
		/* move left */
		xb=xa;
		yb=ya-1;
		if(yb==0)
			yb=xb;
		relax(xa, ya, xb, yb);
		/* move right up */
		xb=xa-1;
		yb=ya;
		if(xb>=1)
		{
			if(yb==xb+1)
				yb=1;
			relax(xa, ya, xb, yb);
		}
		/* move left up */
		xb=xa-1;
		yb=ya-1;
		if(xb>=1)
		{
			if(yb==0)
				yb=xb;
			relax(xa, ya, xb, yb);
		}
	}
	return 0;
}

int main(void)
{
	int i, j;
	scanf("%d", &N);
	for(i=1; i<=N; i++)
		for(j=1; j<=i; j++)
			scanf("%d", s[i]+j);
	spfa(N, 1);
	printf("%d\n", dst[1][1]);
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值