zoukankan      html  css  js  c++  java
  • [好好学习] kick start round c- B

    鉴于Round E要到了...  错过这个村就没这个店了0.0所以整理一下
    此处加一个大纲。markdown在博客园怎么用…… 
    算了格式在这先发出来吧。。and  要有目标qwq。!

    ## 题目2 Circuit Board

    这个在LeetCode上的84 是个经典问题。LeetCode我都还只做到了.. 反正很少的,也没有接手Hard,easy感觉总是水水过去,medium也很少很少。
    下一步说不定可以在github上维护一下?分单独的题解和分开的题解……完全可以在幕布上写了再移植过去的。(心情复杂.jpg)也可以不移植

    ### 题意

    300*300矩阵,给定一大堆数字,使得每行中的最大值、最小值的差不超过K,满足这些条件的最小子矩阵是多少。

    ### false (大部分false的删了……)

    o(n^3)的做法。
    开始想的是并查集归属,串串儿一样噜过去,但是其实有点emmmm
    对于这样的情况,只连续的找到个体然后从个体开始蔓延是不行的。
    2 2 2 4 
    4 2 2 2 
    2 2 2 4
    有种感觉,你需要抛开种族偏见,不能这样狭隘的去想,而且n很小,可以直接枚举两维,再来一维
    首先呢,我们用一个三维布尔数组来记录,f[i][l][r],记录的是i行的从 l 处到 r 处,此段里能否达到"不超过E"的条件。
    这里是很死板的,甚至不用考虑最大值如果有两个的问题,只需预处理,枚举l和r。
    好。如果布尔类型已经确定了

    ### 布尔怎么更新?

    想了想,还是要至少更新n*(n-1)/2个。
    那真的好笑。如果跟前面比是可,然后大小都没越界,
    当前我在的位置是a2,当前已有len匹配到了(算了a2) ,那么1~ a2-len填No,a2-len+1 ~ a2填Yes(true)。
    大小越界怎么看呢?
    嗯,这个好像也是有时效性的,用最笨 的办法,那不如 满足K的时候正着来,不满足的时候1~a2-len+1依然可,后面一边走一边维护tmpmax和tmpmin
    再想。
    如果直接维护l和r呢?
    嗯,这里,思维的差距就体现出来了。我们我在上面写的方法可以是可以,但是相当麻烦,而且有没有感觉到,有一种"特殊化"的感觉。
    抛开这些再想想,在本文末尾,有提供一维怎么解答,可以nlogn,但没必要。
    这个处理是和主程序分开写的,完全可以分开写,枚举的意思就是...
    直接暴力的l和r,哪怕n^2的直接跑一遍,每次只看一个名为“l到r"的区间,只写一个false or true。即使这样n平方复杂度也足够了
    剥离出来统一的看,思维要上升一个高度。。

    ### true =================================

    我觉得好蠢哦,上面可以验证都是false的,高度根本不用管。
    与其这样写题解,还是自己捋顺了是最好的吧……
    ……………………
    这个题只有一句话。枚举l和r,那么这个串串的宽度是确定的,l和r已经n^2了
    宽度确定后,到底有多长,就直接判断yes和no,然后使用累加,再乘以r-l+1就可了。
    为什么要这么做?题中说要验证最长的块,那么是长度(横着)确定,去竖着撸一下更好呢,还是竖着确定,横着撸一串最好呢
    显然,应该长度确定,然后看有几行能符合这个条件。直接一行一行看就可以了(图一)
    如果是宽度确定的话,即使是继续扩展,是没用的,因为并不是以这个作区分的,可以看到1 1 3 这样按照这种划分方式并不能说明,因为这也不是题目的本意。(图二)
    那么写一下代码。好累啊打解析打的手疼我不想写了(buxing
    写个例子:
    99 3 4 0 
    2 2 2 3          
    3 2 2 2 
    2 2 2 3
    26分到手……  思路理清之后,是没问题的,只是我写错了一个== , 一个就是更新的时候没把1,1这样的首部更新进去
    关键是思路啊!!!这还是很简单的啊!!!!26分啊!!!!kickstart错过就没了啊啊啊啊!!!
     
    最后粘一下代码
    #include<iostream>
    #include<algorithm>
    #include<queue>
    using namespace std;
    int n;
    bool f[305][305][305];
    int a[305][305];
    int a1, a2, k;
    int main() {
     int t; cin >> t;
     int kase = 0;
     while (t--) {
      //f好像不用清空 直接初始化就好
      //输入 
      cin >> a1 >> a2 >> k;
      for (int i = 1; i <= a1; i++) {
       for (int j = 1; j <= a2; j++) {
        cin >> a[i][j];
       }
      }
     
      //对数据处理 初始化bool f
      bool ff; int now;
      
      for (int i = 1; i <= a1; i++) {//
       for (int left= 1; left <= a2; left++) { //下面的列
        f[i][left][left] = true;
        int maxx = a[i][left]; int minn = a[i][left];
        //【惊!我这里多写了个等号】
        //【惊!2 我忘记把第一个考虑进去!了耶】
        ff = true;
        for (int right = left+1 ; right <= a2; right++) {
         if (ff == false)f[i][left][right] = false;
         else {
          now = a[i][right];
          maxx = max(maxx, now);
          minn = min(minn, now);
          if (minn + k<now ||maxx-k>now)
           ff = false;
          f[i][left][right] = ff;
         }
         //这个数和minn maxx比较一下就好了 同时更新一下
         // 如果已经是false了 那就全盘都是false好l
        }
       }
      }
     /*
      for (int i = 1; i <= a1; i++) {//行
       for (int left = 1; left <= a2; left++) { //下面的列
        for (int right = left; right <= a2; right++) {
         cout << f[i][left][right]<<" ";
        }
        cout << endl;
       }
       cout << endl;
      }
     
      */
      int maxans = -1;int ans = 0;
      // ... 好.. 那处理完了还剩一次最后的循环和拍
      for (int l = 1; l <= a2; l++) {
       for (int r = l; r <= a2; r++) {
        ans = 0;
        for (int i = 1; i <= a1; i++) {
         if (f[i][l][r] == true) {
          ans += (r - l + 1);
          maxans = max(ans, maxans);
         }
         else {
          ans = 0;
         }
        }
       }
      }
      cout <<"Case #"<<++kase<<": "<< maxans << endl;
     }
     return 0;
    }
     

    ### 变形

    但就是说这样题目是个有名的变形,还有:
    这个是... 饿示意图..  这个题目的意思相当于是让我们这样求。实际上可以转化到leetcode的这样题目:
     
     
     

    ### 问题扩展:

    #### 如果是一维的?

    看起来直接横着过去就行。可以则加,不行则扔
    但是有个问题,就是最大值最小值,如果是 3 4 5 7 2 7 后面来了个1,这不是完了吗,简单的双指针失效了。
    有点作弊的做法:用mutiset。
    而且要s.erase(s.find(7)) 这样只会删除一个,否则两个7都没了
    看最大的只要s.rbegin()即可。越界就往前走(删除),不越界就安全,可以达到nlogn复杂度。

    #### 如果是三维的?

    想象一下,实际上n^5来 n^4在限制长度,相当于一个长方形桶,满足则继续,好像预处理有点麻烦
  • 相关阅读:
    autocomplete自动完成搜索提示仿google提示效果
    实现子元素相对于父元素左右居中
    javascript 事件知识集锦
    让 IE9 以下的浏览器支持 Media Queries
    「2013124」Cadence ic5141 installation on CentOS 5.5 x86_64 (limited to personal use)
    「2013420」SciPy, Numerical Python, matplotlib, Enthought Canopy Express
    「2013324」ClipSync, Youdao Note, GNote
    「2013124」XDMCP Configuration for Remote Access to Linux Desktop
    「2013115」Pomodoro, Convert Multiple CD ISO to One DVD ISO HowTo.
    「2013123」CentOS 5.5 x86_64 Installation and Configuration (for Univ. Labs)
  • 原文地址:https://www.cnblogs.com/lx2331/p/11370111.html
Copyright © 2011-2022 走看看