Beyond the Void
BYVoid
USACO FEB08 Silver Meteor Shower 流星雨
本文正體字版由OpenCC轉換

動態規劃

該題滿足滿足動態規劃的無後效性和最優子結構,但是對於最大情況,有3003001000個狀態。由於狀態過多且無法壓縮,只好搜索。(不排除有壓縮的方法)

搜索

由於此題求得是最少花費的時間,所以最好用廣度優先搜索是一種較好的方法,直接的BFS可以通過。而DFS需要加優化才能通過。

以時間爲階段劃分,記錄當前點所在的座標。每次產生式規則都有上下左右四種可能,對於走到流星雨的位置上的點要去除。

在初始化階段,算出最終的“安全點”,即流星雨結束以後沒有被砸的點。搜索中第一次走到了安全點,就是最少需要的時間。

/*
ID: cmykrgb1
PROG: meteor
LANG: C++
*/

#include <iostream>
#define MAX 302
#define MAXT 50001
using namespace std;

typedef struct
{
	int x,y,t;
}star;

class tQueue
{
public:
	class linklist
	{
	public:
		linklist* next;
		star value;
		linklist()
		{
			next=0;
		}
	};
	linklist *first,*last;
	bool used[MAX][MAX];
	int size;
	void add(star p)
	{
		if (size==0)
			first=last=new linklist;
		else
			last=last->next=new linklist;
		last->value=p;
		size++;
		used[p.x][p.y]=true;
	}
	star del()
	{
		star rtn=first->value;
		linklist *tfirst=first;
		first=first->next;
		delete tfirst;
		size--;
		used[rtn.x][rtn.y]=false;
		return rtn;
	}
	void reset()
	{
		size=0;
		first=last=0;
		memset(used,0,sizeof(used));
	}
	tQueue()
	{
		reset();
	}
};

star S[MAXT];
bool Die[MAX][MAX];
bool Map[MAX][MAX];
bool F[MAX][MAX];
int N;
int dx[4]={0,0,1,-1},dy[4]={1,-1,0,0};
tQueue Q;

inline int cmp(const void *a,const void *b)
{
	return ((star *)a)->t - ((star *)b)->t;
}

inline bool inrange(int x,int y)
{
	return x>=0 && x<MAX && y>=0 && y<MAX;
}

void put(int i,bool M[][MAX])
{
	if (i==0)return;
	int x=S[i].x,y=S[i].y;
	if (inrange(x,y))
		M[x][y]=true;
	if (inrange(x+1,y))
		M[x+1][y]=true;
	if (inrange(x-1,y))
		M[x-1][y]=true;
	if (inrange(x,y+1))
		M[x][y+1]=true;
	if (inrange(x,y-1))
		M[x][y-1]=true;
}

void init()
{
	int i;
	freopen("meteor.in","r",stdin);
	freopen("meteor.out","w",stdout);
	cin >> N;
	for (i=1;i<=N;i++)
	{
		cin >> S[i].x >> S[i].y >> S[i].t;
		put(i,Die);
	}
	qsort(S+1,N,sizeof(S[0]),cmp);
	S[N+1].t=S[N].t+1;
}

int bfs()
{
	int i,j=0,T;
	star F,Y;
	F.x=F.y=F.t=0;
	Q.add(F);
	while (Q.size)
	{
		F=Q.del();
		if (!Die[F.x][F.y])
			return F.t;
		Y.t=F.t+1;
		if (Y.t>S[j].t)
		{
			while (Y.t>S[j].t)
				put(j++,Map);
		}
		if (Map[F.x][F.y])
			continue;
		for (i=0;i<4;i++)
		{
			Y.x=F.x+dx[i];
			Y.y=F.y+dy[i];
			if (inrange(Y.x,Y.y) && !Map[Y.x][Y.y] && !Q.used[Y.x][Y.y])
			{
				Q.add(Y);
			}
		}
	}
	return -1;
}

int main()
{
	int Ans;
	init();
	Ans=bfs();
	cout << Ans << endl;
	return 0;
}

上次修改時間 2017-02-03

相關日誌