zoukankan      html  css  js  c++  java
  • 【GMOJ4016】圈地为王

    题目

    题目链接:https://gmoj.net/senior/#main/show/4016
    \(n\)\(m\) 列的网格中,你要圈一些地。
    你从左上角出发,最后返回左上角,路径内部的区域视为被你圈住。 你不可以进入网格内部, 只能在边上行走。 你的路径不能在左上角以外自交, 但是边足够宽, 你可以重复经过而不自交。
    网格中有一些格子对你很重要,你要尽量圈住它;而另一些格子对你有坏处,你不能圈住它。
    求圈住 \(i\) 个重要的格子的最小路径长度。

    思路

    这道题挺妙的。
    考虑如果一个格子正上方的边经过了奇数次,那么这个点最终就被围住了,如果它上方的点经过了偶数次,那么就没有被围住。
    由于特殊点(重要点+坏点)只有\(10\)个。考虑状压。
    \(f[i][j][S]\)表示现在走到点\((i,j)\),每一个重要点的上方经过的次数的奇偶性为\(S\)的最少步数。
    那么可以\(bfs\)转移,注意维护\(S\)即可。
    时间复杂度\(O(2^knm)\),其中\(k\)表示特殊点的个数。

    代码

    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    const int N=55,MAXN=1025,Inf=1e9;
    const int dx[]={0,0,0,-1,1},dy[]={0,-1,1,0,0};
    int n,m,cnt,Sbad,f[N][N][MAXN],S[N][N],id[N][N],ans[N];
    char a[N][N];
    queue<int> qx,qy,qs;
    
    void bfs()
    {
    	memset(f,0x3f3f3f3f,sizeof(f));
    	f[1][1][0]=0;
    	qx.push(1); qy.push(1); qs.push(0);
    	while (qx.size())
    	{
    		int x=qx.front(),y=qy.front(),s=qs.front();
    		qx.pop(); qy.pop(); qs.pop();
    		for (int i=1;i<=4;i++)
    		{
    			int xx=x+dx[i],yy=y+dy[i],ss;
    			if (yy!=y) ss=s^S[x][min(y,yy)];
    				else ss=s;
    			if (xx<1 || yy<1 || xx>n || yy>m || f[xx][yy][ss]<Inf) continue;
    			f[xx][yy][ss]=f[x][y][s]+1;
    			qx.push(xx); qy.push(yy); qs.push(ss);
    		}
    	}
    }
    
    int main()
    {
    	for (int i=1;scanf("%s",a[i]+1)>0;i++) n++;
    	m=strlen(a[1]+1)+1; n++;
    	for (int i=1;i<n;i++)
    		for (int j=1;j<m;j++)
    			if (a[i][j]!='.')
    			{
    				id[i][j]=++cnt;
    				if (a[i][j]=='X') Sbad|=(1<<id[i][j]-1);
    				for (int k=1;k<=i;k++)
    					S[k][j]|=(1<<id[i][j]-1);
    			}
    	bfs();
    	memset(ans,0x3f3f3f3f,sizeof(ans));
    	for (int i=1;i<(1<<cnt);i++)
    		if (!(i&Sbad))
    		{
    			int s=0;
    			for (int j=i;j;j>>=1) s+=(j&1);
    			ans[s]=min(ans[s],f[1][1][i]);
    		}
    	for (int i=1;ans[i]<Inf;i++)
    		printf("%d\n",ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    java中的匿名内部类总结
    (转)NIO与AIO,同步/异步,阻塞/非阻塞
    (转)也谈BIO | NIO | AIO (Java版)
    socket Bio demo
    (转)socket Aio demo
    (转)深入理解Java的接口和抽象类
    (转)Java:类与继承
    (转)Java中的static关键字解析
    (转)java字节流和字符流的区别
    (整理)MyBatis入门教程(一)
  • 原文地址:https://www.cnblogs.com/stoorz/p/12283859.html
Copyright © 2011-2022 走看看