1月赛-吃pizza-正方形简单dp

月赛里的简单题(所以我当然是没做出来啊),要用动态规划实现,有easy版的和normal版的

dp: dp跟递归查不多,关键都是数学里的递推公式(状态转移方程),递归用函数实现;

 

put

第一行两个正数n,m, k, 分别表示矩阵的行数、矩阵的列数、被吃掉的块数。

接下来有k行,每行有两个数x, y, 表示在x行y列的那块批萨被吃掉了。

easy:(1 <= n, m <= 500, k <= min(500, n*m))   normal::(1 <= n, m <= 5000, k <= min(5000, n*m))

Output

一个整数表示LZDFDSMLL有多少种不同的正方形批萨可以吃。

Sample Input 1

3 3 0

Sample Output 1

14

Sample Input 2

3 3 1
2 2

Sample Output 2

81

想象一下正方形 如果上左上左三个地方都有边长为n的正方形,他们就能拼成一个新n个的正方形,股状态转移方程;
dp[i][j]=min(dp[i-1][j],dp[i][j-1],dp[i-1][j-1])
ps:normal与easy的唯一区别是 总的矩阵规模不同
当是m,n=5000时
ans大概是 5000*5000+4999*4999+. . .+1=n(n+1)(2n+1)/6=5000*5001*10001/6=41 679 167 500
所以要用longlong储存结果

代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int pic[5500][5500],dp[5500][5500];
int  min(int a,int b,int c){
    return min(min(a,b),c);
}
int main(){
    memset(pic,0,sizeof(pic));
    memset(dp,0,sizeof(dp));
    int mk,nk,m,n,k;
    long long ans=0;
    scanf("%d%d%d",&m,&n,&k);
    while(k--){
        scanf("%d%d",&mk,&nk);
        pic[mk][nk]=1;
    }
    
    for(int i=1;i<=m;i++)
      for(int j=1;j<=n;j++)
        if(pic[i][j]==0){
            dp[i][j]=min(dp[i-1][j],dp[i][j-1],dp[i-1][j-1])+1;
            ans+=dp[i][j];
        }
        printf("%lld",ans);
    return 0;
}

 




posted @ 2019-01-21 10:43  易如鱼  阅读(283)  评论(2编辑  收藏  举报