BZOJ3205: [Apio2013]机器人

来源:互联网 发布:8路监控网络交换机 编辑:程序博客网 时间:2024/06/05 04:07

卡常卡了好久qwq

可以先用记忆化搜索搜出每个位置往四个方向走会走到哪,注意判走到已经走过的地方避免死循环
f[l][r][i][j]表示在(i,j)合成机器人l~r的最小花费

f[l][r][i][j]=minf[l][r][di][dj]+1di,dj>i,j
f[l][r][i][j]=min(f[l][k][i][j]+f[k+1][j][i][j])
对于第二个转移,我们按长度从小到大dp,处理到f[l,r,i,j]时枚举k就行了
对于第一个转移,本来要用spfa,因为转移的边权都相同,可以bfs
维护两个队列,把初始状态放在第一个队列,拓展出来的状态放进第二个队列,每次取出两个队列的队头比较,用小的去拓展

code:

#include<set>#include<map>#include<deque>#include<queue>#include<stack>#include<cmath>#include<ctime>#include<bitset>#include<string>#include<vector>#include<cstdio>#include<cstdlib>#include<cstring>#include<climits>#include<complex>#include<iostream>#include<algorithm>#define ll long long#define inf 1e9using namespace std;const int maxn = 505;const int maxk = 10;const int maxd = 4;const int dx[] = {-1,0,1,0};const int dy[] = {0,1,0,-1};int n,m,K;// 11 +1  12 -1int a[maxn][maxn];struct point{int x,y;}d[maxn][maxn][maxd],nul;bool v[maxn][maxn][maxd];bool cmp(const int &x,const int &y){    if(!x||!y||x>n||y>m||a[x][y]==-1) return false;    return true;}point search(const int x,const int y,int k){    if(v[x][y][k]) return nul;    if(d[x][y][k].x) return d[x][y][k];    int tk=k;    v[x][y][tk]=true;    if(a[x][y]==11) k=(k+1)%maxd;    if(a[x][y]==12) k=(k+3)%maxd;    int nx=x+dx[k],ny=y+dy[k];    if(!cmp(nx,ny)) d[x][y][tk]=(point){x,y};    else d[x][y][tk]=search(nx,ny,k);    v[x][y][tk]=false;    return d[x][y][tk];}struct node{int x,y,d;}t[maxn*maxn]; int tp;queue<node>q1,q2; int h1,h2;inline bool cmpt(const node x,const node y){return x.d<y.d;}int f[maxk][maxk][maxn][maxn];char str[maxn];int main(){    nul.x=nul.y=-1;    scanf("%d%d%d",&K,&m,&n);    for(int i=1;i<=n;i++)    {        scanf("%s",str);        for(int j=1;j<=m;j++)        {            char cc=str[j-1];            if(cc=='x') a[i][j]=-1;            else if(cc=='.') a[i][j]=0;            else if(cc=='A') a[i][j]=12;            else if(cc=='C') a[i][j]=11;            else a[i][j]=cc-'0';        }    }    for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) for(int k=0;k<maxd;k++) d[i][j][k].x=d[i][j][k].y=0;    for(int i=1;i<=n;i++) for(int j=1;j<=m;j++)    {        for(int k=0;k<maxd;k++) if(d[i][j][k].x==0)             d[i][j][k]=search(i,j,k);    }    for(int l=1;l<=K;l++) for(int r=1;r<=K;r++) for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) f[l][r][i][j]=-1;    for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(a[i][j]>0&&a[i][j]<10)        f[a[i][j]][a[i][j]][i][j]=0;    for(int L=1;L<=K;L++)    {        for(int l=1;l+L-1<=K;l++)        {            int r=l+L-1;            tp=0;            for(int k=l;k<r;k++) for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(a[i][j]!=-1)            {                int &tmp=f[l][r][i][j];                if(f[l][k][i][j]!=-1&&f[k+1][r][i][j]!=-1)                {                    int temp=f[l][k][i][j]+f[k+1][r][i][j];                    if(tmp==-1||tmp>temp) tmp=temp;                }            }            for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(f[l][r][i][j]!=-1)                t[++tp]=(node){i,j,f[l][r][i][j]};            sort(t+1,t+tp+1,cmpt);            for(int i=1;i<=tp;i++) q1.push(t[i]);            h1=h2=inf;            if(!q1.empty()) h1=(q1.front()).d;            while(h1!=inf||h2!=inf)            {                if(h1<=h2)                {                    node now=q1.front(); q1.pop();                    int x=now.x,y=now.y;                    if(f[l][r][x][y]==h1)                    {                        for(int k=0;k<maxd;k++) if(d[x][y][k].x!=-1)                        {                            int nx=d[x][y][k].x,ny=d[x][y][k].y,&kk=f[l][r][nx][ny];                            if(kk==-1||kk>h1+1)                            {                                kk=h1+1;                                q2.push((node){nx,ny,kk});                            }                        }                    }                }                else                {                    node now=q2.front(); q2.pop();                    int x=now.x,y=now.y;                    if(f[l][r][x][y]==h2)                    {                        for(int k=0;k<maxd;k++) if(d[x][y][k].x!=-1)                        {                            int nx=d[x][y][k].x,ny=d[x][y][k].y,&kk=f[l][r][nx][ny];                            if(kk==-1||kk>h2+1)                            {                                kk=h2+1;                                q2.push((node){nx,ny,kk});                            }                        }                    }                }                h1=h2=inf;                if(!q1.empty()) h1=(q1.front()).d;                if(!q2.empty()) h2=(q2.front()).d;            }        }    }    int re=-1;    for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(f[1][K][i][j]!=-1)        if(re>f[1][K][i][j]||re==-1) re=f[1][K][i][j];    printf("%d\n",re);    return 0;}
原创粉丝点击