【NOI2014模拟7.11】【WC2008游览计划加强】挖宝藏
来源:互联网 发布:软件主管岗位职责 编辑:程序博客网 时间:2024/05/19 05:29
Description
Solution
可以发现,直接做spfa会比较难做。
我们考虑把一层一层的做。
首先有一个很显然的结论:一层的挖过得洞一定是一棵树。
单层的话,很容易想到状压DP。
肯定要DP每层的每个节点覆盖宝藏的情况且当前这个节点被挖过。
那么我们设g[i,j,s]表示点的坐标为(i,j)覆盖宝藏的情况为s。
为了合并s,我们肯定要先枚举s。
然后g[i,j,s]=min(g[i,j,s’]+g[i],j,s^s’-a[p][i][j]),s’≠∅
但是这个只是在合并自己的情况。
那么我们还需要更新相邻的值。
g[x+1,y,s]=min(g[x,y,s]+a[p][x+1][y])
g[x-1,y,s]=min(g[x,y,s]+a[p][x-1][y])
g[x,y+1,s]=min(g[x,y,s]+a[p][x][y+1])
g[x,y-1,s]=min(g[x,y,s]+a[p][x][y-1])
然后这个地方用spfa来优化。
这个东西相当于转移的时候不考虑是否覆盖宝藏,而是延伸这个树的枝叶(不会形成环,因为是最短路,所以是个树)
然后枝叶拓展完之后再向上面那样把两个不相交的非空子集合并。
这样就可以把一层给做完了。
然后每个点在向上一层开一个洞(从下往上做),在上一层开一个超级宝藏(就是说要进去二进制状态),来表示下面层的值。
假设1集合是超级宝藏,那么
最后答案是
Code
#include<iostream>#include<stdio.h>#include<string.h>#include<algorithm>#include<math.h>#define fo(i,a,b) for(i=a;i<=b;i++)#define fod(i,a,b) for(i=a;i>=b;i--)using namespace std;const int maxn=15;typedef long long ll;ll i,j,l,t,n,m,ans,h,p,x,y,s,xx,yy,ss;ll a[15][15][15],k[15];ll g[15][15][2049],f[15][15][2049],er[15],head,tail,bz[15][15][15];ll fang[4][2]={0,1,0,-1,1,0,-1,0};int data[100007][2];bool az[15][15];int main(){ freopen("treasure.in","r",stdin); freopen("treasure.out","w",stdout);// freopen("fan.in","r",stdin); scanf("%d%d%d",&h,&n,&m); er[0]=1;fo(i,1,10)er[i]=er[i-1]*2; fo(i,1,h*n){ fo(j,1,m) scanf("%d",&a[(i-1)/n+1][(i-1)%n+1][j]); } fo(i,1,h){ scanf("%d",&k[i]); fo(j,1,k[i]){ scanf("%d%d",&x,&y); bz[i][x][y]=j; } } fod(p,h,1){ memcpy(f,g,sizeof(f));memset(g,127/2,sizeof(g)); fo(i,1,n){ fo(j,1,m){ g[i][j][1]=f[i][j][er[k[p+1]+1]-1]+a[p][i][j]; if(bz[p][i][j])g[i][j][er[bz[p][i][j]]]=a[p][i][j]; } } fo(s,1,er[k[p]+1]-1){ fo(i,1,n){ fo(j,1,m){ for(l=((s-1)&s);l;l=((l-1)&s)){ g[i][j][s]=min(g[i][j][s],g[i][j][s^l]+g[i][j][l]-a[p][i][j]); } } } head=0;tail=0; fo(i,1,n)fo(j,1,m){ data[++tail][0]=i,data[tail][1]=j;az[i][j]=1; } while(head<tail){ xx=data[++head][0],yy=data[head][1]; fo(i,0,3){ x=xx+fang[i][0],y=yy+fang[i][1]; if(x<1||x>n||y<1||y>m)continue; if(g[xx][yy][s]+a[p][x][y]<g[x][y][s]){ g[x][y][s]=g[xx][yy][s]+a[p][x][y]; if(!az[x][y]){ data[++tail][0]=x,data[tail][1]=y; az[x][y]=1; } } } az[xx][yy]=0; } } } ans=0x7fffffff; fo(i,1,n)fo(j,1,m)ans=min(g[i][j][er[k[1]+1]-1],ans); printf("%lld\n",ans);}
- 【NOI2014模拟7.11】【WC2008游览计划加强】挖宝藏
- 【JZOJ3737】【NOI2014模拟7.11】挖宝藏(treasure)
- 【NOI2014模拟7.11】挖宝藏(treasure)
- 【BZOJ2595】 [Wc2008]游览计划
- [bzoj2595][WC2008]游览计划
- bzoj2595: [Wc2008]游览计划
- 2595: [Wc2008]游览计划
- Bzoj2595: [Wc2008]游览计划
- 【WC2008】bzoj2595 游览计划
- BZOJ 2595 [Wc2008]游览计划
- BZOJ 2595: [Wc2008]游览计划
- JZOJ 3737. 【NOI2014模拟7.11】挖宝藏(treasure)
- SPFA维护dp——【NOI2014模拟7.11】挖宝藏
- Wc2008 游览计划(STNT + 输出路径)
- WC2008 游览计划 斯坦纳树
- 【BZOJ2595】【Wc2008】游览计划、斯坦纳树
- 2595: [Wc2008]游览计划 斯坦纳树
- 【bzoj2595】[Wc2008]游览计划 斯坦纳树
- 1006:换个格式输出整数
- 物联网之绿色出行
- 判断手机号是否是素数
- 解决pycharm左侧项目文件名中文字体乱码情况?中文显示口口口口......
- scikit learn 中pca 的用法
- 【NOI2014模拟7.11】【WC2008游览计划加强】挖宝藏
- Oracle12C基本常识(五)
- 包含min函数的栈
- c语言初级阶段知识整理(一)
- Unity3D游戏场景优化之批处理
- GCC主要数据结构之infile
- 字符串切割
- 顺时针打印矩阵
- 塔防大战unity5.5版本系列(part6)