好神啊……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 }