好神啊……Orz zyf && PoPoQQQ

  为啥跟斯坦纳树扯上关系了?我想是因为每个点(robot)都沿着树边汇到根的时候就全部合起来了吧= =这个好像和裸的斯坦纳树不太一样,那个是无向最小生成树,这个是有向图……

  引用题解:

令f[l][r][i][j]表示在点(i,j)将编号在[l,r]区间内的机器人全部合并的最小推动次数

则有动规方程组:

f[l][r][i][j]=min{f[l][r][_i][_j]+1} ( (_i,_j)->(i,j) )

f[l][r][i][j]=min(f[l][temp][i][j]+f[temp+1][r][i][j]) (l<=temp<r)

我们首先用记忆化搜索处理出每个点向四个方向推动后会到哪

然后利用根据这两个方程跑斯坦纳树即可

下面是细节部分:

1.转向器有环 因此会无限递归爆系统栈 标记一下就好

2.处理上面那个之后本机测还是会爆系统栈 没事交上去就不爆了

3.SPFA有一个优化 不加会T

观察这个图 发现所有边的边权都是1 如果是单源的话SPFA可以进化成广搜

现在是多源 因此我们可以这样做:

维护两个队列,将初始所有的点按照距离排序后从小到大加入队列1

每次拓展出的点加入队列2

每次取出点的时候,如果队列1队尾元素的距离小于队列2 就把队列1的队尾元素拿去松弛 否则就用队列2的

这样做之后除了排序之外复杂度是线性的

排序的log可以用计数排序省掉,但是直接sort也能过,无妨

然后这题就搞掉了。。。。。。

但是蒟蒻的快排程序就TLE了啊……然后用计数排序的MLE了QAQ

只能献上我的膝盖

  1 //APIO 2013 robots
  2 #include<queue>
  3 #include<cstdio>
  4 #include<cstring>
  5 #include<cstdlib>
  6 #include<iostream>
  7 #include<algorithm>
  8 #define rep(i,n) for(int i=0;i<n;++i)
  9 #define F(i,j,n) for(int i=j;i<=n;++i)
 10 #define D(i,j,n) for(int i=j;i>=n;--i)
 11 #define pb push_back
 12 using namespace std;
 13 typedef long long LL;
 14 inline int getint(){
 15     int r=1,v=0; char ch=getchar();
 16     for(;!isdigit(ch);ch=getchar()) if(ch=='-')r=-1;
 17     for(; isdigit(ch);ch=getchar()) v=v*10+ch-'0';
 18     return r*v;
 19 }
 20 const int N=510,INF=1e9;
 21 #define debug
 22 /*******************template********************/
 23 const int fx[]={1,0,-1,0},
 24             fy[]={0,1,0,-1};//down,right,up,left
 25 int n,w,h,mp[N][N],vis[N][N][4],ti;
 26 char s[N];
 27 struct pii{int X,Y;}G[N][N][4],b[N*N];
 28 queue<pii> q1,q2;
 29 bool inq[N][N];
 30 int f[N][N][10][10];
 31 pii dfs(int x,int y,int k){
 32     if (vis[x][y][k]==ti) return (pii){0,0};
 33     if (vis[x][y][k]) return G[x][y][k];
 34     vis[x][y][k]=ti;
 35     int kk=k;
 36     if (mp[x][y]==2) kk=(k+1)%4;
 37     else if (mp[x][y]==3) kk=(k+3)%4;
 38     int tx=x+fx[kk],ty=y+fy[kk];
 39     if (mp[tx][ty]==0) return G[x][y][k]=(pii){x,y};
 40     return G[x][y][k]=dfs(tx,ty,kk);
 41 }/*
 42 vector<pii>E[N*N];
 43 void count_sort(pii *b,int n,int l,int r){
 44     int mx=0;
 45     rep(i,N*N) E[i].clear();
 46     F(i,1,n){
 47         E[f[b[i].X][b[i].Y][l][r]].pb(b[i]);
 48         mx=max(mx,f[b[i].X][b[i].Y][l][r]);
 49     }
 50     int tot=0;
 51     F(i,0,mx) rep(j,E[i].size())
 52         b[++tot]=E[i][j];
 53 }*/
 54 int l,r;
 55 bool cmp(pii a,pii b){
 56     return f[a.X][a.Y][l][r]<f[b.X][b.Y][l][r];
 57 }
 58 int main(){
 59 #ifndef ONLINE_JUDGE
 60     freopen("robot.in","r",stdin);
 61     freopen("robot.out","w",stdout);
 62 #endif
 63     n=getint(); w=getint(); h=getint();
 64     F(i,1,h){
 65         scanf("%s",s+1);
 66         F(j,1,w){
 67             F(l,1,n) F(r,l,n) f[i][j][l][r]=INF;
 68             if (s[j]=='x') mp[i][j]=0;
 69             else if (s[j]=='A') mp[i][j]=2;
 70             else if (s[j]=='C') mp[i][j]=3;
 71             else if (s[j]=='.') mp[i][j]=1;
 72             else {int t=mp[i][j]=s[j]-'0'+10; f[i][j][t-10][t-10]=0;}
 73         }
 74     }
 75 #define FOR F(i,1,h)F(j,1,w)
 76     FOR if (mp[i][j]) rep(k,4) ++ti,dfs(i,j,k);
 77     F(len,1,n)
 78         for(l=1,r=l+len-1;r<=n;l++,r++){
 79             int tot=0;
 80             FOR{
 81                 F(k,l,r-1) f[i][j][l][r]=min(f[i][j][l][r],f[i][j][l][k]+f[i][j][k+1][r]);
 82                 if (f[i][j][l][r]!=INF) b[++tot]=(pii){i,j},inq[i][j]=1;
 83             }
 84 //            count_sort(b,tot,l,r);
 85             sort(b+1,b+tot+1,cmp);
 86             F(i,1,tot) q1.push(b[i]);
 87             while(!q1.empty()||!q2.empty()){
 88                 pii t;
 89                 if (q1.empty()) t=q2.front(),q2.pop();
 90                 else if (q2.empty()) t=q1.front(),q1.pop();
 91                 else{
 92                     pii t1=q1.front(),t2=q2.front();
 93                     if (f[t1.X][t1.Y][l][r]<f[t2.X][t2.Y][l][r]) t=t1,q1.pop();
 94                     else t=t2,q2.pop();
 95                 }
 96                 int x=t.X,y=t.Y,tx,ty; inq[x][y]=0;
 97                 rep(i,4){
 98                     tx=G[x][y][i].X,ty=G[x][y][i].Y;
 99                     if (!tx||!ty) continue;
100                     if (f[tx][ty][l][r]>f[x][y][l][r]+1){
101                         f[tx][ty][l][r]=f[x][y][l][r]+1;
102                         if (!inq[tx][ty]){
103                             inq[tx][ty]=1;
104                             q2.push((pii){tx,ty});
105                         }
106                     }
107                 }
108             }
109         }
110     int ans=INF;
111     FOR ans=min(ans,f[i][j][1][n]);
112     printf("%d\n",ans==INF?-1:ans);
113     return 0;
114 }
View Code

相关文章: