洛谷2021年07月月赛参加总结


一、前言

6月份的“比赛荒”之后,洛谷举办了2021年07月月赛。这次我还是参加Div.2。

以下只讲我会做的题目(事实上也只会做一道,B题和C题都是暴力骗分)。

二、A:远古档案馆(Ancient Archive)

传送门:https://www.luogu.com.cn/problem/P7724?contestId=46177

首先,当空格数量为2~4时,初始方阵肯定可以经变换后与最终方阵相同,因为此时方块可以任意移动。

然后,当空格数量为0时,方块不可移动。此时,直接判定两个方阵是否相同即可。

最后是难点:当空格数量为1时的判断。

其实也不难,重复以下判断12遍:

  • 如果空格在左上角,则将左下角的方格往上移;

  • 如果空格在左下角,则将右下角的方格往左移;

  • 如果空格在右下角,则将右上角的方格往下移;

  • 如果空格在右上角,则将左上角的空格往右移。

每一步过后,判断两个方阵是否一致。如果一致,直接输出Yes。

如果移动了12次,还没有一致的情况,则输出No。

移动12次过后,方阵恰好形成一个循环。所以只用移动12次。

$AC$ 代码:

#include<cstdio>
using namespace std;
int start_graph[3][3],end_graph[3][3];
int space_count;
int space_x,space_y;
bool equal(int a[3][3],int b[3][3])
{
	for(int i=1;i<=2;i++)
	{
		for(int j=1;j<=2;j++)
		{
			if(a[i][j]!=b[i][j])
			{
				return false;
			}
		}
	}
	return true;
}
int main()
{
	for(int i=1;i<=2;i++)
	{
		for(int j=1;j<=2;j++)
		{
			scanf("%d",&start_graph[i][j]);
			if(!start_graph[i][j])
			{
				space_count++;
				space_x=i;
				space_y=j;
			}
		}
	}
	for(int i=1;i<=2;i++)
	{
		for(int j=1;j<=2;j++)
		{
			scanf("%d",&end_graph[i][j]);
		}
	}
	if(space_count<=4&&space_count>=2)
	{
		printf("Yes\n");
		return 0;
	}
	else if(space_count==0)
	{
		if(equal(start_graph,end_graph))
		{
			printf("Yes\n");
		}
		else
		{
			printf("No\n");
		}
		return 0;
	}
	else
	{
		int oper_graph[3][3];
		for(int i=1;i<=2;i++)
		{
			for(int j=1;j<=2;j++)
			{
				oper_graph[i][j]=start_graph[i][j];
			}
		}
		for(int i=1;i<=12;i++)
		{
			if(space_x==1&&space_y==1)
			{
				oper_graph[1][1]=oper_graph[2][1];
				oper_graph[2][1]=0;
				if(equal(oper_graph,end_graph))
				{
					printf("Yes\n");
					return 0;
				}
				space_x=2;
			}
			else if(space_x==2&&space_y==1)
			{
				oper_graph[2][1]=oper_graph[2][2];
				oper_graph[2][2]=0;
				if(equal(oper_graph,end_graph))
				{
					printf("Yes\n");
					return 0;
				}
				space_y=2;
			}
			else if(space_x==2&&space_y==2)
			{
				oper_graph[2][2]=oper_graph[1][2];
				oper_graph[1][2]=0;
				if(equal(oper_graph,end_graph))
				{
					printf("Yes\n");
					return 0;
				}
				space_x=1;
			}
			else if(space_x==1&&space_y==2)
			{
				oper_graph[1][2]=oper_graph[1][1];
				oper_graph[1][1]=0;
				if(equal(oper_graph,end_graph))
				{
					printf("Yes\n");
					return 0;
				}
				space_y=1;
			}
		}
	}
	printf("No\n");
	return 0;
}

三、B:珍珠帝王蟹(Crab King)

对于本题,我同时使用了暴力算法和非暴力算法。

对于Subtask1,由于数据较小,可以使用 $DFS$ 暴力搜索。

对于Subtask2,由于 $v>0$,可以证明,先加后乘是最优的选择。

这就能拿 $48$ 分了。

代码:

#include<cstdio>
#include<algorithm>
using namespace std;
struct pearl_object
{
	char op;
	long long num;
}add_pearl[100005],mul_pearl[100005],pearl[100005];
int add_cnt,mul_cnt;
int n;
long long ans=-0x7fffffffff;
bool flag=true;
int dfs_array[100005];
bool visit[100005];
void dfs(int x)
{
	if(x>n)
	{
		long long temp_ans=0;
		for(int i=1;i<=n;i++)
		{
			if(pearl[dfs_array[i]].op=='+')
			{
				temp_ans+=pearl[dfs_array[i]].num;
			}
			else
			{
				temp_ans*=pearl[dfs_array[i]].num;
			}
		}
		//printf("%lld\n",temp_ans);
		if(temp_ans>ans)
		{
			ans=temp_ans;
		}
	}
	for(int i=1;i<=n;i++)
	{
		if(!visit[i])
		{
			visit[i]=true;
			dfs_array[x]=i;
			dfs(x+1);
			visit[i]=false;
		}
	}
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		char op[2];
		long long num;
		scanf("%s%lld",&op,&num);
		if(num<=0)
		{
			flag=false;
		}
		if(op[0]=='+')
		{
			add_cnt++;
			add_pearl[add_cnt].op=op[0];
			add_pearl[add_cnt].num=num;
		}
		else
		{
			mul_cnt++;
			mul_pearl[mul_cnt].op=op[0];
			mul_pearl[mul_cnt].num=num;
		}
	}
	if(flag)
	{
		ans=0;
		for(int i=1;i<=add_cnt;i++)
		{
			ans+=add_pearl[i].num;
		}
		for(int i=1;i<=mul_cnt;i++)
		{
			ans*=mul_pearl[i].num;
			ans%=998244353;
		}
		if(ans<0)
		{
			ans=(ans+998244353)%998244353;
		}
		printf("%lld\n",ans);
	}
	else
	{
		for(int i=1;i<=add_cnt;i++)
		{
			pearl[i].op=add_pearl[i].op;
			pearl[i].num=add_pearl[i].num;
		}
		for(int i=1;i<=mul_cnt;i++)
		{
			pearl[i+add_cnt].op=mul_pearl[i].op;
			pearl[i+add_cnt].num=mul_pearl[i].num;
		}
		dfs(1);
		printf("%lld\n",ans);
	}
	return 0;
}

四、C:天体探测仪(Astral Detector)

本题我也只能用暴力算法了。

代码:

#include<cstdio>
#include<cstring>
using namespace std;
int n;
int input[805][805];
bool visit[805];
int dfs_array[805];
bool answer_flag;
int get_min(int index,int length)
{
	register int minn=input[1][dfs_array[index]];
	for(register int i=2;i<=length;i++)
	{
		if(minn>input[1][dfs_array[i+index-1]])
		{
			minn=input[1][dfs_array[i+index-1]];
		}
	}
	return minn;
}
void dfs(int x)
{
	if(answer_flag)
	{
		return;
	}
	if(x>n)
	{
		for(register int i=2;i<=n;i++)
		{
			bool appear[n];
			memset(appear,0,sizeof(appear));
			for(register int j=1;j<=n-i+1;j++)
			{
				int minn=get_min(j,i);
				bool flag=false;
				for(register int k=1;k<=n-i+1;k++)
				{
					if(input[i][k]==minn&&!appear[k])
					{
						appear[k]=true;
						flag=true;
						break;
					}
				}
				if(!flag)
				{
					return;
				}
			}
		}
		for(register int i=1;i<=n;i++)
		{
			printf("%d ",input[1][dfs_array[i]]);
		}
		printf("\n");
		answer_flag=true;
		return;
	}
	//printf("Test\n");
	for(register int i=1;i<=n;i++)
	{
		if(answer_flag)
		{
			return;
		}
		if(!visit[i])
		{
			visit[i]=true;
			dfs_array[x]=i;
			dfs(x+1);
			visit[i]=false;
		}
	}
} 
int main()
{
	scanf("%d",&n);
	for(register int i=1;i<=n;i++)
	{
		for(register int j=1;j<=n-i+1;j++)
		{
			scanf("%d",&input[i][j]);
		}
	}
	dfs(1);
	return 0;
}

五、总分

本场比赛,我一共获得了 $174$ 分,排名第 $370$ 名。

WBqNVK.png


文章作者: cyrxdzj
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 cyrxdzj !
  目录