这套好丧……跟别的画风好不一样(中国风?)。提答没做也没测,假装只有两题吧。140/200

 

T1.ROBOTS

题目大意:h*w的网格上有n个机器人编号1~n,网格上有空地、墙、顺/逆时针转向器,每次可以把一个机器人朝一个方向推,机器人碰到空地会继续前进,碰到转向器会转向,碰到墙会在前一格停止,同一时间只能有一个机器人在动,编号连续的机器人可以合体,例如2号和3号合成[2,3],[2,3]和[4,6]合成[2,6],问把所有机器人合成一个最少要推几下,无解输出-1。(n<=9,h,w<=500)

思路:先记忆化搜索预处理出每个格子朝四个方向推各会推到哪里(注意可能会无限循环),用f[i][j][k][l]表示[i,j]并成一个机器人位于(k,l)格至少要推几下(内存较紧,需要hash),考虑dijkstra,堆的log难以接受,我想了个方法:答案肯定不会太大,于是每种权值开一个队列,这样复杂度是每次转移O(1),由于还要区间合并,最后时间复杂度大概是O(n^3hw),空间同样。不过实际上这个n^3不是满的,所以理论上应该是很科学的,不过我写了vector,常数好像有点大,本来想手写个链表加上内存回收搞不好就过了,因为懒而且还要打T2暴力就放弃了,最后得分85/100(都是T)。

#include<cstdio>
#include<cstdlib>
#include<vector>
#include<queue>
using namespace std;
#define MN 500
#define MQ 11250000
struct pos{int x,y;}t[MN+5][MN+5][4];
const int o[4][2]={{0,-1},{-1,0},{0,1},{1,0}};
char g[MN+5][MN+5];
int d[MQ+5],p[9][9],pl[45],pr[45],pn,x,y,l,r;
pos work(int x,int y,int f)
{
    if(t[x][y][f].x)return t[x][y][f];
    t[x][y][f]=(pos){-1,-1};
    int r;
    if(g[x][y]=='.'||(g[x][y]>='1'&&g[x][y]<='9'))r=f;
    if(g[x][y]=='A')r=f?f-1:3;
    if(g[x][y]=='C')r=f<3?f+1:0;
    return t[x][y][f]=(g[x][y]&&g[x][y]!='x')?
        work(x+o[r][0],y+o[r][1],r):(pos){x-o[f][0],y-o[f][1]};
}
inline int hash(int x,int y,int l,int r){return x<0?-1:((x-1)*500+y-1)*pn+p[l][r];}
inline void dehash(int z){l=pl[z%pn];r=pr[z%pn];y=(z/=pn)%500+1;x=z/500+1;}
struct MyPQ
{
    vector<queue<int> > v;int x;
    void push(int x,int z)
    {
        if(x<0||(d[x]&&d[x]<=z))return;d[x]=z;
        while(v.size()<z)v.push_back(queue<int>());
        v[z-1].push(x);
    }
    inline int top(){return v[x].front();}
    inline void next(){for(v[x].pop();v[x].empty()&&x<v.size();++x);if(x==v.size())puts("-1"),exit(0);}
    inline void pop(){for(next();x>=d[v[x].front()];next());}
}q;
int main()
{
    int n,w,h,i,j,k,z,zz;
    scanf("%d%d%d",&n,&w,&h);--n;
    for(i=1;i<=h;++i)scanf("%s",g[i]+1);
    for(i=0;i<9;++i)for(j=i;j<9;++j)pl[pn]=i,pr[pn]=j,p[i][j]=pn++;
    for(i=1;i<=h;++i)for(j=1;j<=w;++j)
    {
        for(k=0;k<4;++k)work(i,j,k);
        if(g[i][j]>='1'&&g[i][j]<='9')q.push(hash(i,j,g[i][j]-'1',g[i][j]-'1'),1);
    }
    while(true)
    {
        dehash(z=q.top());q.pop();
        if(l==0&&r==n)return printf("%d",d[z]-1),0;
        for(i=0;i<l;++i)if(d[zz=hash(x,y,i,l-1)])q.push(hash(x,y,i,r),d[z]+d[zz]-1);
        for(i=8;i>r;--i)if(d[zz=hash(x,y,r+1,i)])q.push(hash(x,y,l,i),d[z]+d[zz]-1);
        for(j=0;j<4;++j)q.push(hash(t[x][y][j].x,t[x][y][j].y,l,r),d[z]+1);
    }
}
View Code

相关文章: