1 条题解

  • 0
    @ 2025-8-24 22:28:34

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar K8He
    あぁ! 夏を今もう一回

    搬运于2025-08-24 22:28:34,当前版本为作者最后更新于2021-02-06 14:12:12,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    原题传送门

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

    20分算法

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

    50分算法

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

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

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

    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];
    		}//回溯 
    	}
    }
    

    上面这份代码是我的神仙老师

    https://www.luogu.com.cn/user/333773

    满分算法

    先给大家看几种合法的333\ast3放置方法:

    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分算法的时间复杂度

    • 1

    信息

    ID
    6439
    时间
    1000ms
    内存
    128MiB
    难度
    4
    标签
    递交数
    0
    已通过
    0
    上传者