bzoj4006: [JLOI2015]管道连接
来源:互联网 发布:virtual copy克隆软件 编辑:程序博客网 时间:2024/05/22 00:42
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4006
思路:
一眼看上去很像斯坦纳树
但是限制稍有不同,只要每种颜色的点联通即可
也就是说最后可能是森林
我听说裸写斯坦纳树有90
所以我们要在外面再套一层DP
f[i][j]还是斯坦纳树的状态,i是以i为根,j是状态为j
先用斯坦纳树求出每种联通状况的最小费用
再设dp[i]表示i这个状态的最小费用
枚举子集时保证颜色相同的连通性相同,转移即可
dp[i]=min(dp[j]+dp[i-j])j是i的子集
#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>const int maxn=11,maxk=11,maxq=105;const int dx[]={0,0,1,-1},dy[]={1,-1,0,0};using namespace std;int n,m,K,head,tail,cnt,pw[maxk+5],w[maxk],q[maxq+10],f[maxn][maxn][1<<maxk],pre[maxn][maxn][1<<maxk],a[maxn][maxn],inf;bool bo[maxn][maxn],vis[maxn][maxn];inline bool in(int x,int y){return x>=0&&x<n&&y>=0&&y<m;}inline int id(int x,int y){return x*10+y;}inline int id2(int x,int y,int s){return s*100+x*10+y;}inline void decode(int sta,int &x,int &y){x=sta/10,y=sta%10;}inline void decode2(int sta,int &x,int &y,int &s){s=sta/100,x=sta%100/10,y=sta%10;} void init(){ pw[0]=1;for (int i=1;i<=11;i++) pw[i]=pw[i-1]<<1; scanf("%d%d",&n,&m); for (int i=0;i<n;i++) for (int j=0;j<m;j++){ scanf("%d",&a[i][j]); if (!a[i][j]) w[K++]=id(i,j); }} void spfa(int s){ //printf("s=%d\n",s); while (head!=tail){ if (++head>maxq) head=1; int sta=q[head],x,y; decode(sta,x,y); //printf("x=%d y=%d\n",x,y); for (int i=0;i<4;i++){ int nx=x+dx[i],ny=y+dy[i]; if (!in(nx,ny)) continue;//printf("nx=%d ny=%d\n",nx,ny); if (f[nx][ny][s]>f[x][y][s]+a[nx][ny]){ f[nx][ny][s]=f[x][y][s]+a[nx][ny]; //printf("ffffffffffffffffffffffffffffff=%d\n",f[nx][ny][s]); pre[nx][ny][s]=id2(x,y,s); if (!bo[nx][ny]){ if (++tail>maxq) tail=1; bo[nx][ny]=1,q[tail]=id(nx,ny); } } } bo[x][y]=0; }} void dfs(int i,int s){ int x,y,nx,ny,t; decode(i,x,y); //printf("x=%d y=%d s=%d\n",x,y,s); vis[x][y]=1; if (!pre[x][y][s]) return; //printf("%d %d\n",id2(x,y,s),pre[x][y][s]); decode2(pre[x][y][s],nx,ny,t); //printf("px=%d py=%d pt=%d\n",nx,ny,t); dfs(id(nx,ny),t); if (x==nx&&y==ny) dfs(id(nx,ny),s^t);} void work(){ memset(f,63,sizeof(f)),inf=f[0][0][0]; for (int i=0,x,y;i<K;i++){ decode(w[i],x,y); f[x][y][pw[i]]=0; } for (int sta=1;sta<pw[K];sta++){ head=tail=0; for (int i=0;i<n;i++) for (int j=0;j<m;j++){ for (int s=sta&(sta-1);s;s=(s-1)&sta) if (f[i][j][sta]>f[i][j][s]+f[i][j][sta^s]-a[i][j]){ f[i][j][sta]=f[i][j][s]+f[i][j][sta^s]-a[i][j]; pre[i][j][sta]=id2(i,j,s); } if (f[i][j][sta]!=inf) q[++tail]=id(i,j),bo[i][j]=1;//printf("x=%d y=%d sta=%d f=%d\n",i,j,sta,f[i][j][sta]); } spfa(sta); } int x,y; decode(w[0],x,y); //printf("xx=%d yy=%d sta=%d\n",x,y,pw[K]-1); printf("%d\n",f[x][y][pw[K]-1]); int nx,ny,ns; decode2(pre[x][y][pw[K]-1],nx,ny,ns); //printf("nx=%d ny=%d ns=%d\n",nx,ny,ns); dfs(w[0],pw[K]-1); for (int i=0;i<n;i++,puts("")) for (int j=0;j<m;j++) if (!a[i][j]) putchar('x'); else if (vis[i][j]) putchar('o'); else putchar('_');} int main(){ //freopen("test.in","r",stdin);freopen("test.out","w",stdout); init(),work(); return 0;}/*8 81 4 1 3 4 2 4 14 3 1 2 0 1 2 33 2 1 3 0 3 1 22 6 5 0 2 4 1 05 1 2 1 3 4 2 55 1 3 1 5 0 1 45 0 6 1 4 5 3 40 2 2 2 3 4 1 1 */
0 0
- bzoj4006: [JLOI2015]管道连接
- BZOJ4006 [JLOI2015]管道连接
- [bzoj4006] [JLOI2015]管道连接
- 【JLOI2015】bzoj4006 管道连接
- Bzoj4006:[JLOI2015]管道连接:斯坦纳树
- 【bzoj4006】[JLOI2015]管道连接 斯坦纳树+子集dp
- [BZOJ4006][JLOI2015]管道连接(斯坦纳树+dp)
- 4006: [JLOI2015]管道连接
- BZOJ 4006 [JLOI2015]管道连接
- BZOJ 4006: [JLOI2015]管道连接
- bzoj4006 管道连接 斯坦纳森林 子集Dp
- 4006: [JLOI2015]管道连接 斯坦纳树+状压dp
- BZOJ 4006: [JLOI2015]管道连接|斯坦纳树
- bzoj 4006: [JLOI2015]管道连接(斯坦纳树)
- bzoj 4006: [JLOI2015]管道连接 斯坦纳树
- 【JLOI2015】通道连接
- [子集DP 斯坦纳树 模板题] HDU 4085 Peach Blossom Spring & BZOJ 4006 [JLOI2015]管道连接
- BZOJ4006【分块】
- ONF开源白皮书:SDN解决方案案例——校园SDN
- Spark1.6的部署配置与运行
- struts2如何防止表单重复提交
- 提高篇项目4——求阶乘函数(2)
- 红黑树
- bzoj4006: [JLOI2015]管道连接
- 如何解决了Mac上网速度很慢的问题
- Tour(二分图最大权匹配)(网络流)
- jdk中Annotation 使用
- 网络基础概念
- Pixhawk之学习杂谈
- 字符设备驱动模型
- .net 文件上传
- Java中ArrayList和LinkedList区别 时间复杂度 与空间复杂度