Connect3 位标记+模拟

传送门:Connect3

初解此题就感觉是模拟,但算了算最暴力的时间复杂度:每次有4种可能的位置,最大走16次,则最大运算4^16 显然爆炸。
这样像显然有点bug,先不考虑黑白交替,就单单考虑每个格子的可能颜色,最大也只有2^16。所以4^16 明显是错误错误。
再考虑到每过一次都要进行颜色交换,最大的预算为C(16,32) (这还是没有考虑不可行解)
如果再过程种剪枝,时间复杂度完全在可行范围内。

但是怎么存储状态呢?
位标记!关于位标记我之前研究过,但做题的时候没有想起来,很遗憾。

综上:此题是模拟+剪枝+位标记。


知道思路了之后就是写代码的时间了,模拟题很考验一个选手的码力如何,今天尝试写了一发,然后明白了:蒟蒻只配写hello world!所以以后这种题还是交个队友吧!(狗头保命)

AC代码如下:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int f1[10]={0,-1,1,0,0,1,-1,1,-1};
int f2[10]={0,1,-1,1,-1,1,-1,0,0};
int a,b,ans=0;
int h[10],s[10][10];
map<ll,int>m;
ll find_it()
{
	ll state=0;
	for(int i=1;i<=4;i++)
	{
		for(int j=1;j<=4;j++)
		{
			state=(state<<2)+s[i][j];
		}
	}
	return state;
}
bool iswin(int p)
{
	for(int i=1;i<=4;i++)
	{
		for(int j=1;j<=4;j++)
		{
			for(int k=1;k<=8;k+=2)
			{
				int x1=i+f1[k],y1=j+f2[k];
				int x2=i+f1[k+1],y2=j+f2[k+1]; 
				if(x1<1||x1>4||y1<1||y1>4||x2<1||x2>4||y2<1||y2>4)continue;
				else 
				{
					if(s[x1][y1]==s[x2][y2]&&s[x1][y1]==s[i][j]&&s[i][j]==p)return 1;
				}
			}
		}	
	}
	return 0;
}
void solve(int now)
{
	ll state=find_it(); 
	if(m[state])return;
	m[state]=1;
	if(iswin(1) || iswin(2) || s[b][a])
	{
    	if(iswin(2) && s[b][a] == 2)
		{
        	ans++;
			return;
        }
        return;
    }
	for(int i=1;i<=4;i++)
	{
		if(h[i]==4)continue;	
		h[i]++;
		s[i][h[i]]=now;
		if(now==1)solve(2);
		else if(now==2)solve(1);
		s[i][h[i]]=0;
		h[i]--;
	}
	return;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	int t;
	cin>>t>>a>>b;
	h[t]++;
	s[t][1]=1; 
	solve(2);
	cout<<ans<<endl;
	return 0;
}

关于这个代码,自认为处理的较好的是iswin() 函数,使用了f1,f2 数组来减少码量。
但写跨的是这个判断。(下面是标答)

if(iswin(1) || iswin(2) || s[b][a])
	{
    	if(iswin(2) && s[b][a] == 2)
		{
        	ans++;
			return;
        }
        return;
    }

但我一开始写的是:(错误写法)

if(iswin(1))return ;
	else if(iswin(2))
	{
		if(s[b][a]==2)
		{
			for(int k=1;k<=8;k+=2)
			{
				int x1=a+f1[k],y1=a+f2[k];
				int x2=b+f1[k+1],y2=b+f2[k+1]; 
				if(s[x1][y1]==s[x2][y2]&&s[x1][y1]==s[a][b]&&s[a][b]==2)
				{
					ans++;
					break;	
				}
			} 	
			return;
		}
		else return ;
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值