ZOJ 2125 Rocket Mania

版权声明:本文为博主原创文章,未经博主允许必须转载。 https://blog.csdn.net/qq_35950004/article/details/87806490

题意:9*6的地图上每个格子里是一种管道(-,T,L,+型或没有),可以把管道旋转 0 , 90 , 180 , 270 ° 0,90,180,270\degree ,问地图有几行的右边界与第X行的左边界通过管道相连。
插头DP论文题,注意常数因子对于程序效率的影响。
用1代表带有火的插头,剩下的用最小表示法。
1.不含1的状态可以舍弃。
2.只含一个x的状态(x>=2)可以把x变为0,极度节省状态数。
虽然我的状态定义和论文不一样,但是不加剪枝的情况下,其实所有定义方式的有效状态都是一样的。

AC Code:

#include<bits/stdc++.h>
#define LL long long
using namespace std;

int n=9,m=6,mask[15];
char mp[15][15];
set<LL>st[2];

LL encode(int pos)
{
	LL ret = 0;
	static int id[15]={},cnt,siz[15]={};
	memset(siz,0,sizeof siz),memset(id,-1,sizeof id),id[0]=0,id[1]=cnt=1;
	for(int i=pos;i>=0;i--) 
		siz[id[mask[i]]==-1?id[mask[i]]=++cnt:id[mask[i]]]++;
	siz[1] = 20 , siz[0] = 20;
	for(int i=pos;i>=0;i--) 
		ret=ret<<4|(siz[id[mask[i]]]==1?0:id[mask[i]]);
	if(pos == n-1) ret <<= 4;
	return ret;
}
void decode(LL ret){ for(int i=0;i<=n;i++) mask[i]=ret&15,ret>>=4; }

void dp(int i,int j,int now)
{
	for(set<LL>::iterator it=st[now^1].begin();it!=st[now^1].end();it++)
	{	decode(*it);
		
		bool flag = 0;
		for(int k=0;k<=n;k++)
			if(mask[k] == 1) 
				flag = 1;
		if(!flag) continue;
		
		
		if(mp[i][j] == '.')
		{
			mask[i] = mask[i+1] = 0;
			st[now].insert(encode(i==n-1?n-1:n));
		}
		if(mp[i][j] == '-')
		{
			int u = mask[i] , v = mask[i+1];
			mask[i] = v , mask[i+1] = 0;
			st[now].insert(encode(i==n-1?n-1:n));
			
			mask[i+1] = u , mask[i] = 0;
			st[now].insert(encode(i==n-1?n-1:n));
		}
		if(mp[i][j] == '+')
		{
			int u = mask[i] , v = mask[i+1];
			if(u && v)
			{
				if(u == 1)
				{
					for(int k=0;k<=n;k++) 
						if(mask[k]==v) 
							mask[k]=u;
				}
				else 
					for(int k=0;k<=n;k++) 
						if(mask[k]==u) 
							mask[k]=v;
			}
			else if(u || v)
				mask[i] = mask[i+1] = u + v;
			else
			{
				mask[i] = mask[i+1] = 13;
			}
			st[now].insert(encode(i==n-1?n-1:n));
		}
		if(mp[i][j] == 'L')
		{
			int u = mask[i] , v = mask[i+1];
			
			mask[i+1] = 0;
			st[now].insert(encode(i==n-1?n-1:n));
			
			mask[i] = 0 , mask[i+1] = v;
			st[now].insert(encode(i==n-1?n-1:n));
			
			mask[i] = mask[i+1] = 13;
			st[now].insert(encode(i==n-1?n-1:n));
			
			if(u && v)
			{
				if(u == 1)
				{
					for(int k=0;k<=n;k++) 
						if(mask[k]==v) 
							mask[k]=u;
				}
				else 
					for(int k=0;k<=n;k++) 
						if(mask[k]==u) 
							mask[k]=v;
			}
			mask[i] = mask[i+1] = 0;
			st[now].insert(encode(i==n-1?n-1:n));
		}
		if(mp[i][j] == 'T')
		{
			int u = mask[i] , v = mask[i+1];
			
			if(u && v)
			{
				if(u == 1)
				{
					for(int k=0;k<=n;k++) 
						if(mask[k]==v) 
							mask[k]=u;
				}
				else 
					for(int k=0;k<=n;k++) 
						if(mask[k]==u) 
							mask[k]=v;
				mask[i+1] = 0;
				st[now].insert(encode(i==n-1?n-1:n));
				
				decode(*it);
				if(u == 1)
				{
					for(int k=0;k<=n;k++) 
						if(mask[k]==v) 
							mask[k]=u;
				}
				else 
					for(int k=0;k<=n;k++) 
						if(mask[k]==u) 
							mask[k]=v;
				mask[i] = 0;
				st[now].insert(encode(i==n-1?n-1:n));
				
				decode(*it);
				mask[i] = mask[i+1];
				st[now].insert(encode(i==n-1?n-1:n));
				mask[i] = u;
				
				mask[i+1] = mask[i];
				st[now].insert(encode(i==n-1?n-1:n));
				mask[i+1] = v;
			}
			else if(u || v)
			{
				mask[i] = u+v , mask[i+1] = 0;
				st[now].insert(encode(i==n-1?n-1:n));
				
				mask[i+1] = u+v , mask[i] = 0;
				st[now].insert(encode(i==n-1?n-1:n));
				
				mask[i] = u , mask[i+1] = v;
				if(mask[i]) mask[i+1] = mask[i];
				else mask[i+1] = mask[i] = 13;
				st[now].insert(encode(i==n-1?n-1:n));
				
				mask[i] = u , mask[i+1] = v;
				if(mask[i+1]) mask[i] = mask[i+1];
				else mask[i+1] = mask[i] = 13;
				st[now].insert(encode(i==n-1?n-1:n));
			}
			else 
			{
				mask[i] = mask[i+1] = 13;
				st[now].insert(encode(i==n-1?n-1:n));
				
				mask[i] = u ,mask[i+1] = v;
				st[now].insert(encode(i==n-1?n-1:n));
			}
		}
	}
}

int main()
{
	int d;
	for(;~scanf("%d",&d);)
	{
		for(int i=0;i<n;i++) scanf("%s",mp[i]);
		memset(mask,0,sizeof mask);
		mask[d] = 1;
		st[0].clear();
		st[0].insert(encode(n));
		int now = 1;
		for(int i=0;i<m;i++)
			for(int j=0;j<n;j++)
				st[now].clear(),dp(j,i,now),now^=1;
		int ans = 0;
		for(set<LL>::iterator it=st[now^1].begin();it!=st[now^1].end();it++)
		{
			decode(*it);
			int cnt = 0;
			for(int k=1;k<=n;k++)
				cnt += (mask[k] == 1);
			ans = max(ans , cnt);
		}
		printf("%d\n",ans);
	}
	
}

猜你喜欢

转载自blog.csdn.net/qq_35950004/article/details/87806490
ZOJ
今日推荐