2025/3/1课堂记录

目录

  1. 牧场的安排(猛兽军团2)
  2. 关灯问题Ⅱ

牧场的安排(猛兽军团2)

猛兽军团1是八向

而这题只有四向

但是这道题有地形限制

所以在求每一行的合法状态时,会发现几乎每行它的合法状态都不同

因此我们就需要新设置一个数组:num用来存储每行合法状态所对应的二进制

值得注意的是:map[i]=(map[i]<<1)+1-x;

这里我们没有把输入的直接存进map里,而是取了反,即1->0,0->1

为啥要取反呢?

因为下面判断一个状态是否合法的时候,是要用到"&"的

这个&,只能看出来是否有重合的1,看不出来0

那就这样,把贫瘠的土地想象成土地上放置有障碍物(盖了房子),表示为1

没盖房子的表示为0

如果一个奶牛的站位和房子重合或者和左移后的另一只奶牛重合

那么这种状态不合法

剩下的就和猛兽军团1差不多了
这个是我自己写的代码,提交AC了

#include<iostream>
using namespace std;
int map[15],sum[15],num[15][250],f[15][250];
int main()
{
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			{
				int x;
				cin>>x;
				map[i]=(map[i]<<1)+1-x;	
			}
	for(int i=1;i<=n;i++)
		for(int j=0;j<(1<<m);j++)
		{
			if(j&(j<<1)||j&(j>>1)||j&map[i])continue;
			sum[i]++;
			num[i][sum[i]]=j;
		}
	num[0][1]=0;
	sum[0]=1;
	f[0][1]=1;
	long long int ans=0;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=sum[i];j++)
		{
			int a=num[i][j];
			for(int k=1;k<=sum[i-1];k++)
			{
				int b=num[i-1][k];
				if(a&b)continue;
				f[i][j]+=f[i-1][k];
			}
			if(i==n)ans+=f[i][j];
		}
	cout<<ans%100000000<<"\n";
/*	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=1<<m;j++)
			cout<<f[i][j];
		cout<<"\n";
	}
	for(int i=1;i<=15;i++)cout<<sum[i];*/
	return 0;
}

关灯问题Ⅱ

看不懂一点

样例就是先按第二个按钮,把中间那盏灯关上

然后再按第一个按钮,把第一盏灯,第三盏灯关掉
直接放代码吧

 #include<bits/stdc++.h>
#define IL inline
#define RI register int
IL void in(int &x)
{
    int f=1;x=0;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
    x*=f;
}
int a[108][18],f[2048],n,m;
int main()
{
    in(n);  // cin  
	in(m);
    memset(f,0x3f,sizeof f);
    
    for(RI i=1;i<=m;i++)      // 读入 
        for(RI j=1;j<=n;j++)
            in(a[i][j]);  
            
    f[(1<<n)-1]=0;     // f[s]= 最少次数 
    //1 表示开着; 0 表示关着; 
    for(RI i=(1<<n)-1;i>=0;i--) // 枚举所有状态 
    {
        for(RI j=1;j<=m;j++)   // 枚举所有开关 
        {
            int now=i;
            for(RI l=1;l<=n;l++) // 枚举所有灯泡 
            {
                if(a[j][l]==0)    // 如果是0,无论这灯是否开,都不管
				    continue;
                if(a[j][l]==1 && (i&(1<<(l-1))))  // 如果a[i][j]为1,那么当这盏灯开了的时候,把它关上,否则不管
				    now^=(1<<(l-1));   // now的l位0 
				    //now=i-(1<<(l-1));
                if(a[j][l]==-1 && !(i&(1<<(l-1))))  //如果为-1的话,如果这盏灯是关的,那么把它打开,否则也不管
				    now^=(1<<(l-1));   // now的l位1 
            }
            f[now]=std::min(f[now],f[i]+1);  //最少要按几下按钮才能全部关掉
        }
    }
    printf("%d",f[0]==1061109567?-1:f[0]);
}