版权声明:作为一个蒟蒻,转载时请通知我这个蒟蒻 https://blog.csdn.net/zyszlb2003/article/details/89469565
欢迎大家访问我的老师的OJ———caioj.cn
题目描述
思路
这道题有点优秀。
先解释一下输入:
一行一行中给出了期间内的N天(不超过365天),接着是N行,给出了市场和节日的时间表。第i行给出了第i天的时间表。它由16个数字组成,0或1, 0表示正常的一天,1表示市场或节日。数字由一个或多个空格分隔。
比如说位置
,则在输入中应该是在
这个位置上。
我们采用二进制来表示,
for(int i=1;i<=n;i++)
{
for(int j=0;j<16;j++)
{
int w;scanf("%d",&w);
(a[i]<<=1)|=w;
}
}
同时为了配套,我们需要在进行递归时,我们也要还原出这个二进制数。
inline int get(int x,int y)
{
return 1<<(16-(x-1)*4-y);
}
int flag=get(x,y)|get(x,y+1)|get(x+1,y)|get(x+1,y+1);//2*2的云,以左上为坐标。
if(flag&a[day])return 0;//看看当前状态所处位置是否有节日。
因为题目说一个地区最多六天不下雨。
经过我慎重地思考(瞎模拟),得出:
只要四个角有过下雨,其他地区就一定有下过雨
所以我们要多开一个数组,记录四个角的状态。
struct node
{
int d[5];
}st;
之后要记录是否来过这里或状态是否合法,以免浪费时间。
由于我太懒,所以我打了状态压缩。
bool pd(int day,int x,int y,node t)
{
for(int i=1;i<=4;i++)if(t.d[i]>6)return 0;
int flag=get(x,y)|get(x,y+1)|get(x+1,y)|get(x+1,y+1);
if(flag&a[day])return 0;
int s=t.d[4]+t.d[3]*8+t.d[2]*64+t.d[1]*512;
if(v[day][(x-1)*3+y][s])return 0;
return v[day][(x-1)*3+y][s]=1;
}
对了,根据题意,应该有九个状态方向。
const int dx[9]={0,1,-1,2,-2,0,0,0,0};
const int dy[9]={0,0,0,0,0,1,-1,2,-2};
AC code
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=370;
const int M=4100;
int n,a[N];
bool v[N][10][M];
const int dx[9]={0,1,-1,2,-2,0,0,0,0};
const int dy[9]={0,0,0,0,0,1,-1,2,-2};
struct node
{
int d[5];
}st;
inline int get(int x,int y)
{
return 1<<(16-(x-1)*4-y);
}
bool pd(int day,int x,int y,node t)
{
for(int i=1;i<=4;i++)if(t.d[i]>6)return 0;
int flag=get(x,y)|get(x,y+1)|get(x+1,y)|get(x+1,y+1);
if(flag&a[day])return 0;
int s=t.d[4]+t.d[3]*8+t.d[2]*64+t.d[1]*512;
if(v[day][(x-1)*3+y][s])return 0;
return v[day][(x-1)*3+y][s]=1;
}
bool dfs(int day,int x,int y,node t)
{
if(day==n+1)return 1;
if(!pd(day,x,y,t))return 0;
for(int i=0;i<9;i++)
{
node nxt=t;
for(int j=1;j<=4;j++)++nxt.d[j];
int nx=x+dx[i],ny=y+dy[i];
if(nx<1||nx>3||ny<1||ny>3)continue;
if(nx==1)
{
if(ny==1)nxt.d[1]=0;
else if(ny==3)nxt.d[2]=0;
}
else if(nx==3)
{
if(ny==1)nxt.d[3]=0;
else if(ny==3)nxt.d[4]=0;
}
if(dfs(day+1,nx,ny,nxt))return 1;
}
return 0;
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
if(!n)break;
memset(a,0,sizeof(a));
memset(v,false,sizeof(v));
for(int i=1;i<=n;i++)
{
for(int j=0;j<16;j++)
{
int w;scanf("%d",&w);
(a[i]<<=1)|=w;
}
}
for(int i=1;i<=4;i++)st.d[i]=1;
puts(dfs(1,2,2,st)?"1":"0");
}
return 0;
}