思路
这道题可以用8个方向的bfs来解决,首先为八个方向编号0-7,八个方向的变化量用dx[]、dy[]来存储,途中经过的点用set来存储(自动去重),记录这个点是否来过用一个<pair<int,int>, bool>类型的map来表示。,假设射线从(0,0)开始,初始方向为向上。
对于每一条射线,将它为分裂前经过的点都加入set中,在分裂的时候由于45度方向,所以会产生(l.flag+1)%8、(l.flag+7)%8两个方向的新的射线,并且分裂数加一,但是如果每次分裂的点都要入队的话,复杂度是指数级别的,肯定要tle,所以我们用map来判断一下新分裂的节点以前是否产生过,如果没有,标记为来过,并且入队,如果前面产生过,则将其舍弃,由于此题的数据特殊,所以会产生大量的重复节点,用map判断后可以极大地降低复杂度。
总结
这个题考试的时候脑抽了,直到八个方向可以用简单的公式考虑统一,但是就是想列八种情况,各种+1-1,把自己整晕了,最后是分裂的时候有一个方向错了,得了0分,不过当时也没有考虑过去重,所以肯定也过不了。感觉设计算法是一定要看一下复杂度。
代码
#include<iostream>
#include<stdio.h>
#include<string>
#include<queue>
#include<set>
#include<map>
using namespace std;
struct light
{
int cnt;
int flag;
int x,y;
light(int cnt_,int flag_,int a,int b)
{
cnt=cnt_;
flag=flag_;
x=a;
y=b;
}
bool operator <(const light& b) const
{
if(cnt!=b.cnt) return cnt<b.cnt;
else if(flag!=b.flag) return flag<b.flag;
else if(x!=b.x) return x<b.x;
else return y<b.y;
}
};
void put(light a)
{
cout<<a.flag<<"("<<a.x<<", "<<a.y<<") "<<endl;
}
int dx[]={0, 1, 1, 1, 0, -1, -1, -1};
int dy[]={1, 1, 0, -1, -1, -1, 0, 1};
int main()
{
queue<light> q;
queue<light> nextq;
light ll(0,0,0,0);
q.push(ll);
set< pair<int,int> >s;
s.insert(pair<int,int>(0,0));
int n;
cin>>n;
int *dis=new int[n];
for(int i=0;i<n;i++)
scanf("%d",&dis[i]);
map<light,bool> global;
set<light> temp;
bool stop=false;
while(!stop)
{
stop=true;
while(!q.empty())
{
light l=q.front();
q.pop();
for(int i=0;i<dis[l.cnt]-1;i++)
{
if(l.flag==0)
s.insert(pair<int,int>(l.x,++l.y));
else if(l.flag==1)
s.insert(pair<int,int>(++l.x,++l.y));
else if(l.flag==2)
s.insert(pair<int,int>(++l.x,l.y));
else if(l.flag==3)
s.insert(pair<int,int>(++l.x,--l.y));
else if(l.flag==4)
s.insert(pair<int,int>(l.x,--l.y));
else if(l.flag==5)
s.insert(pair<int,int>(--l.x,--l.y));
else if(l.flag==6)
s.insert(pair<int,int>(--l.x,l.y));
else if(l.flag==7)
s.insert(pair<int,int>(--l.x,++l.y));
}
if(l.cnt<n-1)
{
light a(l.cnt+1,(l.flag+1)%8,l.x+dx[(l.flag+1)%8],l.y+dy[(l.flag+1)%8]),
b(l.cnt+1,(l.flag+7)%8,l.x+dx[(l.flag+7)%8],l.y+dy[(l.flag+7)%8]);
if(global.find(a)==global.end())
{
global[a]==1;
nextq.push(a);
s.insert(pair<int,int>(a.x,a.y));
}
if(global.find(b)==global.end())
{
global[b]==1;
nextq.push(b);
s.insert(pair<int,int>(b.x,b.y));
}
}
}
while(!nextq.empty())
{
q.push(nextq.front());
nextq.pop();
stop=false;
}
}
cout<<s.size()<<endl;
}