City Game【暑假集训P题】【DP动态规划】

        最后一道题,刚好做完了,但对于这道题,我一定要提上来讲解一下它,这道题来来回回用了3~4种不同的方法花式T题,最后A的那一瞬间悲喜交加!

Bob is a strategy game programming specialist. In his new city building game the gaming environment is as follows: a city is built up by areas, in which there are streets, trees,factories and buildings. There is still some space in the area that is unoccupied. The strategic task of his game is to win as much rent money from these free spaces. To win rent money you must erect buildings, that can only be rectangular, as long and wide as you can. Bob is trying to find a way to build the biggest possible building in each area. But he comes across some problems – he is not allowed to destroy already existing buildings, trees, factories and streets in the area he is building in. 

Each area has its width and length. The area is divided into a grid of equal square units.The rent paid for each unit on which you're building stands is 3$. 

Your task is to help Bob solve this problem. The whole city is divided into K areas. Each one of the areas is rectangular and has a different grid size with its own length M and width N.The existing occupied units are marked with the symbol R. The unoccupied units are marked with the symbol F. 
InputThe first line of the input contains an integer K – determining the number of datasets. Next lines contain the area descriptions. One description is defined in the following way: The first line contains two integers-area length M<=1000 and width N<=1000, separated by a blank space. The next M lines contain N symbols that mark the reserved or free grid units,separated by a blank space. The symbols used are: 

R – reserved unit 

F – free unit 

In the end of each area description there is a separating line. 
OutputFor each data set in the input print on a separate line, on the standard output, the integer that represents the profit obtained by erecting the largest building in the area encoded by the data set.Sample Input
2
5 6
R F F F F F
F F F F F F
R R R F F F
F F F F F F
F F F F F F

5 5
R R R R R
R R R R R
R R R R R
R R R R R
R R R R R
Sample Output
45
0

    我看过无数的人说这道题与之前的这一道题是相同的,但我觉得也相同也不同,这样子的一道题让我感触还是挺深的。

    思路:它让我们求的是折服图中由'F'构成的矩形的面积最大值*3的值,我想到的第一个方法,也就是最接近answer的一个方法就是把每个点的值从左往右排,遇到'R'就清零然后在继续累加,毫无疑问,这样的思路跟前面做的这道题方法是相同的,我们之后只要一一遍历它的左右极限即可,但是T了2发之后就发现没那么简单。

        改进后的正解:想了个办法优化,既然从左往右这样叠出来的矩阵方法不可以,那么不如从上往下用这样的方法进行操作,然而这样的方法会比之前从左往右简单,因为这个方法是套在for循环之中的,就可以减少一层循环做到优化,我们每一排开始输入,然后就直接进行操作,假如输入的是'F',那么对于这一列,我们列长就增加了,同理,遇到'R',那么这就是个断点了,我们执行清零处理,然后从新排长度,与此同时,我们对于每一个j列进行找到它的左右极端直接求面积与ans比较,这样可以省出时间与空间。求左右极端的方法与这道题目相同

完整代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int n,m;
int h[1005];        //用来记录横排此处的位置的高度
int l[1005];
int r[1005];      //左右分别能到达的最远距离
int main()
{
    int T;
    scanf("%d",&T);
 //   int Case=0;
    while(T--)
    {
     //   Case++;
     //   if(Case>1)cout<<endl;
        int ans=0;
        scanf("%d%d",&n,&m);
        memset(l, 0, sizeof(l));
        memset(r, 0, sizeof(r));
        memset(h, 0, sizeof(h));
        h[0]=h[m+1]=-1;
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=m; j++)
            {
                char temp[5];
                scanf("%s",temp);
                if(temp[0]=='F')       //若'F',高加一
                {
                    h[j]++;
                }
                else
                {
                    h[j]=0;
                }
                l[j]=j;
                while(h[l[j]-1]>=h[j])
                {
                    l[j]=l[l[j]-1];
                }
            }
            for(int j=m; j>=1; j--)
            {
                r[j]=j;
                while(h[r[j]+1]>=h[j])
                {
                    r[j]=r[r[j]+1];
                }
            }
            for(int j=1; j<=m; j++)
            {
                int s=h[j]*(r[j]-l[j]+1);
                if(s>ans)
                {
                    ans=s;
                }
            }
        }
        printf("%d\n",ans*3);
    }
    return 0;
}

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wuliwuliii

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值