• 洛谷 1736 创意吃鱼法


      传送门

    最开始想到的枚举  

      其实最开始想错了一些地方,或者说一些地方没有想清楚。

      现在说一下改完之后的:

      按行和列枚举点

      第三层循环有两个 分别是鱼的对角线是从左上到右下 和 从左下到右上

      枚举的点分别是正方形的左上角点和右上角点

      分开来循环只有一个目的:方便剪枝

      举个栗子:
      4 6
      0 1 0 1 0 0            我们现在枚举到(1, 2) 这个点
      0 0 1 0 1 0    鱼在左上到右下的对角线的情况
      1 1 0 0 0 1    枚举到正方形边长到3的时候就发现不行了
      0 1 1 0 1 0    这时直接break 因为边长为4的情况肯定不行了

      要注意很多细节啊 调了挺久的

     1 #include<iostream>
     2 #include<cstdio>
     3 #define go(i,a,b) for(register int i=a;i<=b;i++)
     4 #define M 2510
     5 using namespace std;
     6 int read()
     7 {
     8     int x=0,y=1;char c=getchar();
     9     while(c<'0'||c>'9') {if(c=='-') y=-1;c=getchar();}
    10     while(c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-'0';c=getchar();}
    11     return x*y;
    12 }
    13 int n,m,ans=1;
    14 bool mp[M][M],f1=0;
    15 bool ck1(int x,int y,int k)      
    16 {
    17     go(i,x,x+k) go(j,y,y+k)
    18     {
    19         if(i-x==j-y && !mp[i][j]) return 0;
    20         if(i-x!=j-y && mp[i][j]) return 0;
    21     }
    22     return 1;
    23 }
    24 bool ck2(int x,int y,int k)
    25 {
    26     int z=x+y;
    27     go(i,x,x+k) go(j,y-k,y)
    28     {
    29         if(i+j==z && !mp[i][j]) return 0;
    30         if(i+j!=z && mp[i][j]) return 0;
    31     }
    32     return 1;
    33 }
    34 int main()
    35 {
    36     n=read();m=read();
    37     go(i,1,n) go(j,1,m) {mp[i][j]=read();if(mp[i][j]) f1=1;}
    38     if(!f1) {puts("0");return 0;}
    39     go(i,1,n) go(j,1,m)
    40     {
    41         int maxn=min(n-i+1,m-j+1);
    42         go(k,ans+1,maxn)
    43         {
    44             if(ck1(i,j,k-1)) ans=k;
    45             else break ;
    46         }
    47         maxn=min(n-i+1,j);
    48         go(k,ans+1,maxn)
    49         {
    50             if(ck2(i,j,k-1)) ans=k;
    51             else break ;
    52         }
    53     }
    54     printf("%d",ans);
    55     return 0;
    56 }
    枚举 View Code

      本来以为会TLE几个点 结果 猝不及防地AC了??

      不过挺慢的 2024ms 开O2 964ms

    小结:   在打代码之前再理一理思路 从头到尾想一遍(毕竟我总是没想清楚而错)

    然后又去想 DP:

      然而我并不会

          优秀题解在这里

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<algorithm>
     5 #include<string>
     6 #include<map>
     7 typedef long long ll;
     8 using namespace std;
     9 int n,m,ans;
    10 int a[2509][2509],f[2509][2509],s1[2509][2509],s2[2509][2509];//s1为横向,s2为纵向 
    11 int main()
    12 {
    13     cin>>n>>m;
    14     //第一遍左上——右下 
    15     for(int i=1;i<=n;i++)
    16     for(int j=1;j<=m;j++)
    17     {
    18         scanf("%d",&a[i][j]);
    19         if(!a[i][j])
    20         {
    21             s1[i][j]=s1[i][j-1]+1;
    22             s2[i][j]=s2[i-1][j]+1;
    23         }
    24         if(a[i][j])
    25         f[i][j]=min(f[i-1][j-1],min(s1[i][j-1],s2[i-1][j]))+1;
    26         ans=max(ans,f[i][j]);
    27     }
    28     //第二遍右上——左下 
    29     memset(f,0,sizeof(f)); 
    30     memset(s1,0,sizeof(s1));//数组置0 
    31     memset(s2,0,sizeof(s2)); 
    32     for(int i=1;i<=n;i++)
    33     for(int j=m;j>=1;j--)
    34     {
    35         if(!a[i][j])
    36         {
    37             s1[i][j]=s1[i][j+1]+1;
    38             s2[i][j]=s2[i-1][j]+1;
    39         }
    40         if(a[i][j])
    41         f[i][j]=min(f[i-1][j+1],min(s1[i][j+1],s2[i-1][j]))+1;
    42         ans=max(ans,f[i][j]);
    43     }
    44     cout<<ans<<endl;
    45     return 0;
    46 }
    DP 题解View Code
    光伴随的阴影
  • 相关阅读:
    C语言单链表创建,插入,删除
    Java乔晓松spring构造函数的注入以及null的注入
    sentilib_语料库项目_search模块的实现
    spring入门(6)set方法注入依赖之null的注入
    Java乔晓松使用Filter过滤器清除网页缓存
    漂亮的弹框
    C#判断各种字符串(如手机号)
    视频数字水印
    数据校验
    SVN 常见问题操作总结
  • 原文地址:https://www.cnblogs.com/forward777/p/10328360.html
Copyright © 2020-2023  润新知