bzoj 3205: [Apio2013]机器人 (斯坦纳树)
来源:互联网 发布:淘宝客服昵称怎么修改 编辑:程序博客网 时间:2024/05/16 01:35
题目描述
传送门
题解
这道题改spfa的姿势+卡常+记忆化,搞了一下午。。。。
考虑怎么转移?
(1)
(2)
对于每一个点还需要预处理
这个转移的方式实际上和斯坦纳树的转移方式基本相同,转移(2)可以用spfa进行松弛。
这道题时限比较卡,所以我们需要改进spfa的方式。
因为所有的边权都是1,所以如果是单源最短路的话我们改成bfs的方式,但是这个是多源的。
我们先将所有可行的位置加入队列,然后对于序列中的点按照f值进行排序,使其从小到大依次存入q1队列中。(计数排序比较快)
然后对于spfa扩展到的点加入q2队列,每次从两个队列的队首选取较小的弹出来进行更新。
代码
#include<iostream>#include<algorithm>#include<cstring>#include<cstdio>#include<queue>#include<ctime>#define N 503#define M 600003using namespace std;int dx[5]={0,1,0,-1},dy[5]={1,0,-1,0};struct data{ int x,y; data(int X=0,int Y=0) { x=X,y=Y; }}dis[N][N][5],q[N*N],h1[M+5];int f[10][10][N][N],n,w,h,INF,vis[N][N][5],ti,tp,sum[M+5],val[N*N];bool can[N][N]; char mp[N][N];data dfs(int x,int y,int k){ if (vis[x][y][k]==ti) return data(-1,0); vis[x][y][k]=ti; if (dis[x][y][k].x!=0) return dis[x][y][k]; int t=k; if (mp[x][y]=='C') k=(k+1)%4; if (mp[x][y]=='A') k=(k+3)%4; int x1=x+dx[k]; int y1=y+dy[k]; if (x1>w||x1<1||y1>h||y1<1||mp[x1][y1]=='x') return dis[x][y][t]=data(x,y); return dis[x][y][t]=dfs(x1,y1,k);}void spfa(int l,int r){ memset(sum,0,sizeof(sum)); memset(can,0,sizeof(can)); int mn=INF,mx=-INF; for (int i=1; i<=tp; i++){ sum[val[i]]++; mn=min(mn,val[i]); mx=max(mx,val[i]); can[q[i].x][q[i].y]=1; } for (int i=mn+1;i<=mx;i++) sum[i]+=sum[i-1]; for (int i=1;i<=tp;i++) h1[sum[val[i]]--]=q[i]; for (int i=1;i<=tp;i++) q[i]=h1[tp-i+1]; int head=0,tail=0,now; data u,v; while (tp||head!=tail){ now=head%M+1; if (head==tail||tp&&f[l][r][q[tp].x][q[tp].y]<f[l][r][h1[now].x][h1[now].y]) u=q[tp--]; else{ head=now; u=h1[head]; } int x=u.x; int y=u.y; can[x][y]=0; for (int i=0;i<4;i++){ int tx=dis[x][y][i].x; int ty=dis[x][y][i].y; if (tx!=-1&&f[l][r][x][y]+1<f[l][r][tx][ty]){ f[l][r][tx][ty]=f[l][r][x][y]+1; if (!can[tx][ty]){ can[tx][ty]=1; tail=tail%M+1; h1[tail]=data(tx,ty); } } } } }int main(){ scanf("%d%d%d",&n,&h,&w); for (int i=1;i<=w;i++) scanf("%s",mp[i]+1); memset(f,127/3,sizeof(f)); INF=f[0][0][0][0]; for (int i=1;i<=w;i++) for (int j=1;j<=h;j++) if (mp[i][j]!='x') for (int k=0;k<4;k++) ++ti,dis[i][j][k]=dfs(i,j,k); for (int i=1;i<=w;i++) for (int j=1;j<=h;j++) if (mp[i][j]>='0'&&mp[i][j]<='9') { int t=mp[i][j]-'0'; f[t][t][i][j]=0; } for (int l=1;l<=n;l++) for (int x=1;x<=n-l+1;x++) { int y=x+l-1; tp=0; for (int i=1;i<=w;i++) for (int j=1;j<=h;j++) { for (int k=x;k<=y-1;k++) f[x][y][i][j]=min(f[x][y][i][j],f[x][k][i][j]+f[k+1][y][i][j]); if (f[x][y][i][j]!=INF) { q[++tp]=data(i,j); val[tp]=f[x][y][i][j]; } } spfa(x,y); } int ans=INF; for (int i=1;i<=w;i++) for (int j=1;j<=h;j++) ans=min(ans,f[1][n][i][j]); printf("%d\n",(ans==INF)?-1:ans);}
0 0
- BZOJ 3205 Apio2013 机器人 斯坦纳树
- bzoj 3205: [Apio2013]机器人 斯坦纳树
- BZOJ 3205 [Apio2013]机器人 斯坦纳树
- bzoj 3205: [Apio2013]机器人 (斯坦纳树)
- 【bzoj3205】[Apio2013]机器人 斯坦纳树
- 3205: [Apio2013]机器人
- bzoj 4774: 修路 (斯坦纳树)
- bzoj 2595: [Wc2008]游览计划(斯坦纳树)
- bzoj 4006: [JLOI2015]管道连接(斯坦纳树)
- 【BZOJ】4774 修路 斯坦纳树
- BZOJ 3205 & UOJ 107 [APIO2013]ROBOTS
- bzoj3205: [Apio2013]机器人
- BZOJ3205: [Apio2013]机器人
- BZOJ 4006 管道连接(最小斯坦纳树+状压DP)
- 【BZOJ】【P2595】【Wc2008】【游览计划】【题解】【斯坦纳树】
- BZOJ 2595 WC 2008 游览计划 斯坦纳树
- BZOJ 2595 Wc2008 游览计划 斯坦纳树
- BZOJ 4006: [JLOI2015]管道连接|斯坦纳树
- sqlite3 数据类型
- secureCRT安装与使
- MATLAB查看数组大小
- 06:登山
- cmake学习笔记
- bzoj 3205: [Apio2013]机器人 (斯坦纳树)
- 从零开始教你制作友善之壁TINY4412----SD卡uboot启动卡
- IMweb_day2
- 自然语言处理系列之Viterbi算法
- C++ dll无法解析的外部符号的问题起因
- 动态规划练习题-5(吃糖果)
- 在Cpython编译器下引用.py文件中的函数
- C++ malloc()、calloc()、realloc()、new[]分配内存方法辨析
- 便捷输出sql查询结果为TXT/CSV文件