zoukankan      html  css  js  c++  java
  • BZOJ1556 墓地秘密

    题意

    费尽周折,终于将众将士的残骸运送到了KD军事基地地底层的大型墓地入口。KD的伙伴和战友们都参加了这次重大的送葬仪式。右边是一扇敞开的大门,进去便是墓地了,左边是一堵凹进去的墙,没有什么特别的地方。 部队缓缓进入右边的门,一切。。。就这么结束了么。。。。。 此时, F却没有跟上队伍,在一般MM都会有的强烈的第六感之下,她来到了左边这堵墙前一探究竟。扫去了重重的灰尘之后,墙上一块凹进去的手掌印清晰可见了。F试着用自己的手对上去,竟刚好合适。稍微用力一按,顿时一声巨响,地上马上裂开一大洞,F和那厚重的墙瞬间一起落入深渊!当其他人听见了巨大的声响而赶来的时候,一切都恢复平静了。只有那堵墙后面的世界,震惊了所有生物。这到底是什么,为什么会在墓地里面? 墙的后面是一个巨大的迷宫!简单的一行字浮现在了一侧的墙上:猛烈撞击所有发亮的机关石。当大伙好奇的蜂拥进迷宫的时候,一块莫名其妙的巨石竟从入口上方落下,将入口完全堵死了!石头上清晰的写了一行字:超过规定时间不能完成任务,全部人都会困死于此。看来,只有硬着头皮去闯,才有可能离开这里,并且探索出这个迷宫的秘密了。 于是大家马上散开,很快摸清了这里的地形,剩下的任务就是轰击石头了。那么。。。论攻击力最高的,自然非功夫DP莫属,而且功夫DP可以使用前滚翻移动法,能够瞬间获得巨大的初速度,并且在直线运动的时候速度将近似光速,质量无穷大,那动能自然就。。。。。。DP每次可以选择朝一个方向滚动,并且可以自己选择在某位置停下来,或者撞击到墙和石头的时候被迫停下来。由于直线速度过快,所以要停下来拐弯自然就是很麻烦的事情。那么只有制定出一个最好的运动方法,使得DP停下来次数最少,才能争取尽量多的时间!
    
    输入:第一行3个正整数N、M和T。表示这是一个N*M的迷宫,并且有T个机关石。 接下来用一个N*M的字符矩阵描述迷宫,`.`表示是空地,`#`表示是墙。 接下来T行每行2个正整数X、Y,描述一个机关石的位置,它在迷宫对应的位置是`#`。不会有两个机关石在同一位置。 最后一行2个正整数X0、Y0,表示DP的初始位置。
    
    输出:一个正整数ANS,表示DP至少要停下来多少次才能撞击完所有的机关石。
    

    (N,M leq 100 , T leq 15)

    分析

    参照hzwer的题解。

    对于40%的数据

    状压墙的撞击情况,然后广搜

    d[x][y][st][dir]表示到x行y列,撞击情况为st,朝向为dir的最小转向数

    对于100%的数据

    只有机关四周的四个格子是有意义的

    只会在这些格子间之间走最短路(可以广搜来求),那么只剩下4T个格子,预处理每个格子到另一个格子撞机关的最少转向次数

    最后状压dp即可,用(f(s,t))表示已撞击状态为s,然后出发点情况为t的最小话费。直接对每个状态枚举转移态即可。

    复杂度(O(4T cdot 4NM + 2^T cdot 4T cdot 4T))

    由于我预处理写的是spfa,会多花些时间

    这题主要难点在于预处理出距离。

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cmath>
    #include<set>
    #include<map>
    #include<queue>
    #include<stack>
    #include<algorithm>
    #include<bitset>
    #include<cassert>
    #include<ctime>
    #include<cstring>
    #define rg register
    #define il inline
    #define co const
    template<class T>il T read()
    {
    	rg T data=0;
    	rg int w=1;
    	rg char ch=getchar();
    	while(!isdigit(ch))
    	{
    		if(ch=='-')
    			w=-1;
    		ch=getchar();
    	}
    	while(isdigit(ch))
    	{
    		data=data*10+ch-'0';
    		ch=getchar();
    	}
    	return data*w;
    }
    template<class T>T read(T&x)
    {
    	return x=read<T>();
    }
    using namespace std;
    typedef pair<int,int> pii;
    typedef long long ll;
    co int INF=0x3f3f3f3f;
    
    co int MAXN=100,MAXT=15;
    int n,m,t;
    char buf[MAXN];
    int rock[MAXN][MAXN];
    int x[MAXT],y[MAXT];
    co int dx[4]={0,0,1,-1},dy[4]={1,-1,0,0};
    
    int p(int x,int d)
    {
    	return 4*x+d;
    }
    
    int dis[4*MAXT+1][4*MAXT+1];
    int d[MAXN][MAXN][4];
    bool inq[MAXN][MAXN];
    queue <pii> Q;
    
    bool inrg(int x,int y)
    {
    	return 0<=x&&x<n&&0<=y&&y<m;
    }
    
    void bfs(int bx,int by,int id)
    {
    	if(!inrg(bx,by)||rock[bx][by])
    		return;
    	memset(d,0x3f,sizeof d);
    	for(int i=0;i<4;++i)
    		d[bx][by][i]=0;
    	Q.push(pii(bx,by));
    	inq[bx][by]=1;
    	while(Q.size())
    	{
    		int x=Q.front().first,y=Q.front().second;
    		Q.pop();
    		inq[x][y]=0;
    		for(int i=0;i<4;++i)
    		{
    			int nx=x+dx[i],ny=y+dy[i];
    			if(!inrg(nx,ny)||rock[nx][ny])
    				continue;
    			for(int j=0;j<4;++j)
    				if(d[x][y][i]+(i!=j)<d[nx][ny][j])
    				{
    					d[nx][ny][j]=d[x][y][i]+(i!=j);
    					if(!inq[nx][ny])
    					{
    						Q.push(pii(nx,ny));
    						inq[nx][ny]=1;
    					}
    				}
    		}
    	}
    	for(int i=0;i<t;++i)
    		for(int j=0;j<4;++j)
    		{
    			int s=INF,nx=x[i]+dx[j],ny=y[i]+dy[j];
    			for(int k=0;k<4;++k)
    				s=min(s,d[nx][ny][k]+(nx+dx[k]!=x[i]||ny+dy[k]!=y[i]));
    			dis[id][p(i,j)]=s;
    		}
    }
    
    int f[1<<MAXT][4*MAXT+1];
    
    void dp()
    {
    	for(int i=0;i<(1<<t);++i)
    		for(int x=0;x<=4*t;++x)
    			f[i][x]=INF;
    	f[0][4*t]=0;
    	for(int i=0;i<(1<<t);++i)
    		for(int x=0;x<=4*t;++x)
    			if(f[i][x]<INF)
    				for(int y=0;y<4*t;++y)
    				{
    					int s=i|(1<<(y/4));
    					f[s][y]=min(f[s][y],f[i][x]+dis[x][y]+1); // 加上到机关石停止的开销 
    				}
    	int ans=INF;
    	for(int x=0;x<=4*t;++x)
    	{
    //		cerr<<"f "<<(1<<t)-1<<" "<<x<<" = "<<f[(1<<t)-1][x]<<endl;
    		ans=min(ans,f[(1<<t)-1][x]);
    	}
    	printf("%d
    ",ans);
    }
    
    int main()
    {
    //	freopen(".in","r",stdin);
    //	freopen(".out","w",stdout);
    	memset(dis,0x3f,sizeof(dis));
    	read(n);read(m);read(t);
    	for(int i=0;i<n;++i)
    	{
    		scanf("%s",buf);
    		for(int j=0;j<m;++j)
    			if(buf[j]=='#')
    				rock[i][j]=1;
    	}
    	for(int i=0;i<t;++i)
    		x[i]=read<int>()-1,y[i]=read<int>()-1; // edit 1: -1
    	for(int i=0;i<t;++i)
    		for(int j=0;j<4;++j)
    			bfs(x[i]+dx[j],y[i]+dy[j],p(i,j));
    	int bx=read<int>()-1,by=read<int>()-1; // edit 1
    	bfs(bx,by,4*t);
    //	for(int i=0;i<=4*t;++i)
    //		for(int j=0;j<=4*t;++j)
    //			cerr<<dis[i][j]<<(j==4*t?'
    ':' ');
    	dp();
    	return 0;
    }
    
  • 相关阅读:
    dede 专题的调用
    dede织梦CMS文件夹目录结构
    [转]Dedecms备份还原网站有效方法
    dede入侵步骤
    dede限制标题长度后,鼠标移到标题,不显示完整的锚文本标题解决方法
    dede列表缩图中,给缩图添加alt锚文本信息的方法
    dede织梦_高级功能function扩展-dede @me
    《DSP using MATLAB》示例Example4.8
    《DSP using MATLAB》示例Example4.7
    《DSP using MATLAB》示例Example4.6
  • 原文地址:https://www.cnblogs.com/autoint/p/10034808.html
Copyright © 2011-2022 走看看