zoukankan      html  css  js  c++  java
  • P1736 创意吃鱼法 (动态规划)

    题目描述

    回到家中的猫猫把三桶鱼全部转移到了她那长方形大池子中,然后开始思考:到底要以何种方法吃鱼呢(猫猫就是这么可爱,吃鱼也要想好吃法 ^_*)。她发现,把大池子视为01矩阵(0表示对应位置无鱼,1表示对应位置有鱼)有助于决定吃鱼策略。

    在代表池子的01矩阵中,有很多的正方形子矩阵,如果某个正方形子矩阵的某条对角线上都有鱼,且此正方形子矩阵的其他地方无鱼,猫猫就可以从这个正方形子矩阵“对角线的一端”下口,只一吸,就能把对角线上的那一队鲜鱼吸入口中。

    猫猫是个贪婪的家伙,所以她想一口吃掉尽量多的鱼。请你帮猫猫计算一下,她一口下去,最多可以吃掉多少条鱼?

    输入输出格式

    输入格式:

    有多组输入数据,每组数据:

    第一行有两个整数n和m(n,m≥1),描述池塘规模。接下来的n行,每行有m个数字(非“0”即“1”)。每两个数字之间用空格隔开。

    对于30%的数据,有n,m≤100

    对于60%的数据,有n,m≤1000

    对于100%的数据,有n,m≤2500

    输出格式:

    只有一个整数——猫猫一口下去可以吃掉的鱼的数量,占一行,行末有回车。

    输入输出样例

    输入样例#1: 
    4 6
    0 1 0 1 0 0
    0 0 1 0 1 0
    1 1 0 0 0 1
    0 1 1 0 1 0
    
    输出样例#1: 
    3

    说明

    右上角的

    1 0 0

    0 1 0

    0 0 1

    Solution

      一开始以为是道DP水题...

      自信满满:

      状态很好定义:

       f [ i ] [ j ] 代表吃到 ( i , j )这个点的时候最多吃多少.

      转移也很好转移,直接从左斜线和右斜线转移过来. 

      

    20分的代码: 

    int main()
    {
         scanf("%d%d",&n,&m);
         for(int i=1;i<=n;i++)
         for(int j=1;j<=m;j++)
         scanf("%d",&c[i][j]);
         f[1][1]=c[1][1];
         for(int i=1;i<=n;i++)
         for(int j=1;j<=m;j++)
         {
            f[i][j]=c[i][j];
            if(i>1&&j>1)
               if(c[i][j]&&c[i-1][j-1])     
                  f[i][j]=max(f[i][j],c[i][j]+f[i-1][j-1]);
            ans=max(ans,f[i][j]);
         }
         memset(f,0,sizeof(f));
         f[1][m]=1;
         for(int i=1;i<=n;i++)
         for(int j=m;j>=1;j--)
         {
             f[i][j]=c[i][j];
            if(i>1&&j<m)
               if(c[i][j]&&c[i+1][j-1])
                  f[i][j]=max(f[i][j],c[i][j]+f[i+1][j-1]);
            ans=max(ans,f[i][j]);
         }
         cout<<ans<<endl;
    }

      然后,才发现自己有几个限制没注意到...一直20分.

      我一开始就有一个误区,即一开始就把所有状态混在一起.

      打得心态崩溃,于是发现还需要两个数组来记录

      当前这个点四周没有1的正方形的最大面积.

      然后其实应该分两个情况来做才好.因为:

      0 0 1

      0 1 0

      0 0 1

      像这样的情况是不能转移的.

      但是用我刚才的状态做,很坑... 所以处理两遍是最好的方式.

      左斜处理一遍,右斜处理一遍.  

      事实证明,题目真的要仔细看...

    代码 

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=2508;
    int n,m,ans;
    int c[maxn][maxn],f[maxn][maxn];
    int f1[maxn][maxn],f2[maxn][maxn];
    int main()
    {
        scanf("%d%d",&n,&m);
        f[1][1]=c[1][1];
        for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
        f[i][j]=c[i][j];
            scanf("%d",&c[i][j]);
            if(!c[i][j])
                f1[i][j]=f1[i][j-1]+1,
                f2[i][j]=f2[i-1][j]+1;
            if(c[i][j])
            f[i][j]=min(f[i-1][j-1],min(f1[i][j-1],f2[i-1][j]))+1;
            ans=max(ans,f[i][j]);
        }
        memset(f,0,sizeof(f)); 
        memset(f1,0,sizeof(f1));
        memset(f2,0,sizeof(f2)); 
        for(int i=1;i<=n;i++)
        for(int j=m;j>=1;j--)
        {
        f[i][j]=c[i][j];
            if(!c[i][j])
                f1[i][j]=f1[i][j+1]+1,
                f2[i][j]=f2[i-1][j]+1;
            if(c[i][j])
            f[i][j]=min(f[i-1][j+1],min(f1[i][j+1],f2[i-1][j]))+1;
            ans=max(ans,f[i][j]);
        }
        cout<<ans<<endl;
    }
  • 相关阅读:
    单元测试(第一阶段+部分第二阶段+部分第三阶段+部分第四阶段)
    构建之法——Team & Scrum & MSF
    Github: 团队账号:https://github.com/ChenRuTing
    Sprint第二个计划
    读其他博客有感~
    冲刺第十天
    冲刺第五天
    冲刺第三天
    冲刺第二天
    冲刺第一天
  • 原文地址:https://www.cnblogs.com/Kv-Stalin/p/9097522.html
Copyright © 2011-2022 走看看