您的位置:首页 > 其它

【动态规划】[luoguP1736]创意吃鱼法

2017-10-20 09:58 387 查看
题目

发表了题解。。

我真的不知道我写的搜索还是DP

反正都差不多吧 - -

怎么搞呢

首先我们用三个数组 map[][]存图 f[][]用来存如果矩阵的对角线是从左上到右下的话 能取得的最大对角线长度 dp[][]则是同理的右上到左下的矩阵

因为每一个有鱼的位置一开始本身就是一个矩阵 所以初始化当map[i][j]=1的时候 dp[i][j]和f[i][j]都为1

然后在我们枚举一个k 往前找 看看有没有多余的1 因为我们要让矩阵尽量的大且题目要求这个矩阵除了对角线之外其他地方都不能有1的 且k只需要枚举到f(dp)[i - 1][j - 1]因为再往前的之前搞f(dp)[i - 1][j - 1]已经枚举过了 再枚举反而会出乱子 然后就是如果满足!map[i - k][j] && !map[i][j - k] && map[i - k][j - k]那么这个矩阵就可以有i-k~i j-k~j那么大 用一个tmp来记录当前对角线增长了多少 最后f(dp)[i][j]再+=tmp一下 就完成了 这样保证对于每一个有鱼的点都能统计到以它为末端的最大的对角线是左上到右下的正方形或者对角线是右上到左下的正方形的对角线长度(没错 我语文很差)

在过程中ans不断更新最大值 最后输出

代码如下

#include<iostream>
#include<cstdio>
#include<cctype>

using namespace std;
#define in = read();
typedef long long ll;
typedef unsigned int ui;
const ll size = 2500 + 10;

int n , m;
int map[size][size];
int ans , tmp , tmp2;
int f[size][size] , dp[size][size];

inline ll read(){
ll num = 0 , f = 1;    char ch = getchar();

while(!isdigit(ch)){
if(ch == '-')   f = -1;
ch = getchar();
}
while(isdigit(ch)){
num = num*10 + ch - '0';
ch = getchar();
}

return num*f;
}

int main(){
n in;    m in;
for(register int i=1;i<=n;i++)
for(register int j=1;j<=m;j++){
map[i][j] in;
if(map[i][j]){
f[i][j] = 1;
dp[i][j] = 1;
ans = 1;
}
}

for(register int i=1;i<=n;i++)
for(register int j=1;j<=m;j++){
if(map[i][j] && map[i - 1][j - 1]){
for(register int k=1;k<=f[i - 1][j - 1];k++){
if(!map[i - k][j] && !map[i][j - k] && map[i - k][j - k])
tmp ++;
else    break;
}
f[i][j] += tmp;
ans = max(ans , f[i][j]);
tmp = 0;
}
}
for(register int i=1;i<=n;i++)
for(register int j=1;j<=m;j++){
if(map[i][j] && map[i - 1][j + 1]){
for(register int k=1;k<=dp[i - 1][j + 1];k++){
//                                        cout<<k<<" "<<map[i - 1][j + 1] + 1<<" " <<i<<" "<<j<<endl;
if(!map[i - k][j] && !map[i][j + k] && map[i - k][j + k])
tmp ++;
else    break;
}
dp[i][j] += tmp;
ans = max(ans , dp[i][j]);
tmp = 0;
}
}
/*
cout<<endl;
for(register int i=1;i<=n;i++){
for(register int j=1;j<=m;j++)
cout<<f[i][j]<<" ";
cout<<endl;
}
cout<<endl;
for(register int i=1;i<=n;i++){
for(register int j=1;j<=m;j++)
cout<<dp[i][j]<<" ";
cout<<endl;
}*/
printf("%d" , ans);
}
/*
4 6
0 0 1 0 1 0
0 1 0 1 0 0
1 0 0 0 1 1
0 1 0 1 1 0

10 10
0 0 1 0 1 0 1 1 1 1
1 1 1 0 1 0 0 0 0 1
0 0 0 0 0 0 0 1 0 1
0 0 0 0 0 0 1 0 1 1
0 0 0 0 0 1 0 0 1 0
0 0 0 0 1 0 0 0 1 1
0 0 0 1 0 0 0 0 1 1
0 0 1 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 1 1
1 0 0 0 0 0 0 0 1 0
*/

//COYG
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: