「解题报告」P7301 【[USACO21JAN] Spaced Out S】

「解题报告」P7301 【[USACO21JAN] Spaced Out S】

原题传送门

神奇的5分算法:直接输出样例。

20分算法

直接把每个点是否有牛的状态DFS一遍同时判断是否合法,时间复杂度约为O(2n2)(因为有判断合法的剪枝所以会比这个低)。而在前四个测试点中N4,用枚举算法在最坏情况下需要运行65536次,时间非常富裕,但是在之后的测试点中就会超时了。

50分算法

每四个方格内都有C42=6种方法放置牛:

  1   2   3   4   5   6
  CC  C.  C.  .C  .C  ..
  ..  C.  .C  C.  .C  CC

DFS每四个方格内的六种情况同时判断是否合法,时间复杂度约为O(6n2)(因为有判断合法的剪枝所以会比这个低)。
部分参考代码:

int a[1001][1001],ans,n;
char v[1001][1001];
string d[]={"cc00","c0c0","c00c","0cc0","0c0c","00cc"};
int dx[]={0,0,1,1};
int dy[]={0,1,0,1};
void dfs(int x,int y){
	int nextx=x,nexty=y+1;
	if(nexty==n) nextx++,nexty = 1;
	if(x>=n){
		int newscore=0;
		for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) newscore+=v[i][j]=='c'?a[i][j]:0;
		ans=max(ans,newscore);//更新答案 
		return;	
	}
	for(int i=0;i<6;i++){
		int match=true;
		string old="";
		for(int j=0;j<4;j++) old+=v[x+dx[j]][y+dy[j]];
		for(int j=0;j<4;j++){
			int row=x+dx[j],col=y+dy[j];
			if(v[row][col]!=' '&&v[row][col]!=d[i][j]){//判断是否合法 
				match=false;
				break;
			}
		}
		if(match){
			for(int j=0;j<4;j++) v[x+dx[j]][y+dy[j]]=d[i][j];
			dfs(nextx,nexty);
			for(int j=0;j<4;j++) v[x+dx[j]][y+dy[j]]=old[j];
		}//回溯 
	}
}

上面这份代码是我的神仙老师 @akic 写的,大家可以去膜拜他

满分算法

先给大家看几种合法的33放置方法:

C.C  CC.  C.C  ..C
C.C  ..C  .C.  CC.
.C.  CC.  C.C  ..C

发现了吧,每一行或每一列的奶牛排列方式一定是交替排列的,而且上一行或上一列的交替排列方式对这一行或这一列交替排列方式没有影响,所以我们只需要先计算每一行的奇数列之和 和 偶数列之和 以及每一列的奇数行之和 和 偶数行之和(建议多读几遍,我当时都写晕了),再取每行的两种交替方式中的最大值,最后再取行上交替排列和列上交替排列的最大值就是答案了。

参考代码:

#include <bits/stdc++.h>
using namespace std;
int n,a,x[1010][2],y[1010][2],num,ans;
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;++i)
		for(int j=1;j<=n;++j)
			scanf("%d",&a),x[i][j%2]+=a,y[j][i%2]+=a;
	for(int i=1;i<=n;++i)
		num+=max(x[i][1],x[i][0]),ans+=max(y[i][1],y[i][0]);
	printf("%d",max(num,ans));
	return 0;
}//为什么大家的代码都这么长啊……

Update 1(2021/2/14):改正了50分算法的时间复杂度

本文作者:K8He

本文链接:https://www.cnblogs.com/K8He/p/P7301.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   K8He  阅读(104)  评论(1编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起