1. 程式人生 > >POJ 1062

POJ 1062

1.Question:

中文題不說什麼了

2.Solution:

本題的難點有兩個 1.建圖 2.限制 建圖: 首先,我們需要明確本圖G是一個有向圖,我們的頂點代表廟我們的物品的編號,圖採用鄰接矩陣儲存,我們的圖中的鄰接矩陣中儲存我們的便宜價格這樣的話,我們每個點只要在限制條件下都可以找到1點,那麼我們就取到達1點的最小值當作我們的答案 限制: 本體的限制說的很明確,但是我們如何處理我們的限制確實非常的苦難,網上的大神采用了區間列舉的思路,我們對SPFA進行操作的時候,我們的鬆弛百年志鬆馳在限制區間範圍的邊才可以 另外,通過本體需要學會一種叫做超級源點的思路,我們的0視作超級源點,該點和其他的點之間的都有連邊,連邊的長度大小是我們的該點除的物品的權值,超級源點的思路非常的有用

3.Code:

/*
Problem: 1062		User: lantianheyeqi
Memory: 240K		Time: 32MS
Language: C++		Result: Accepted
*/
#include"iostream"
#include"cstdio"
#include"cstring"
#include"cstdlib"
#include"cmath"
#define N 0x3f3f3f3f

int n,m;
int map[105][105];
int l[105];

void init_map()
{
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(i!=j) map[i][j]=N;
			else map[i][j]=0;
		}
	}
}

int SPFA(int j,int k)
{
	int queue[100*100];
	int head=1;
	int tail=2;
	bool book[105];
	memset(book,0,sizeof(book));
	book[0]=1;
	queue[1]=0;
	int dis[105];
	for(int i=1;i<=n;i++) dis[i]=N;
	dis[0]=0;
	while(head!=tail)
	{
		for(int i=1;i<=n;i++)
		{
			if(l[i] < j || l[i] > k) continue;
			if(dis[i] > dis[queue[head]]+map[queue[head]][i])
			{
				dis[i] = dis[queue[head]]+map[queue[head]][i];
				if(book[i]==0)
				{
					book[i]=1;
					queue[tail++]=i;
				}
			}
		}
		book[queue[head]]=0;
		head++;
	}
	return dis[1];
}

int main()
{
	scanf("%d%d",&m,&n);
	init_map();
	for(int i=1;i<=n;i++)
	{
		int x,y,z;
		scanf("%d%d%d",&x,&y,&z);
		map[0][i]=x;
		l[i]=y;
		for(int j=1;j<=z;j++)
		{
			int number,money;
			scanf("%d%d",&number,&money);
			map[number][i]=money;
		}
	}
	int mink=N;
	for(int i=l[1]-m;i<=l[1];i++)
	{
		int w=SPFA(i,i+m);
		if(w<mink) mink=w;
	}
	printf("%d\n",mink);
	return 0;
}