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