1. 程式人生 > >P1736 創意吃魚法 (動態規劃)

P1736 創意吃魚法 (動態規劃)

線上 sin 一行 col 地方 一起 就是 LG 轉移

題目描述

回到家中的貓貓把三桶魚全部轉移到了她那長方形大池子中,然後開始思考:到底要以何種方法吃魚呢(貓貓就是這麽可愛,吃魚也要想好吃法 ^_*)。她發現,把大池子視為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;
}

P1736 創意吃魚法 (動態規劃)