• 洛谷P3147 [USACO16OPEN]262144 2048 合并 倍增 动归 递推


    洛谷P3147 [USACO16OPEN]262144
    2048 合并
    题意 每次可以把相邻的两个相同的数字合并, 如x 和 x 合并之后 值就是 x+1
    求最终最大能够合并到的数字大小

    题解 一种 做法类似倍增 动归 递推
    f[ i ][ j ] 表示 从第 i -- f[ i ][ j ]-1 位 这几位的和是 j
    然后就可以递推 或者说动归了,因为要相同j是由前后两个相同 j-1合并而来的,
    f[ i ][ j ] = f[ f[ i ][ j-1 ] ][ j-1 ] 合并当然是从小到大合并的
    因为先把小的合并了,大的合并机会才会更多嘛,另一个理由就是根据公式,
    在算 j 时 需要事先算出 i-1 才行

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <cstdlib>
     4 #include <cmath>
     5 #include <algorithm>
     6 #include <string>
     7 #include <iostream>
     8 #include <iomanip>
     9 using namespace std ; 
    10 
    11 const int maxn = 300011,maxm = 61; 
    12 
    13 int n,ans ; 
    14 int a[maxn],f[maxn][maxm-1] ; 
    15 
    16 inline int read() 
    17 {
    18     char ch = getchar() ; 
    19     int x = 0,f = 1 ; 
    20     while(ch<'0'||ch>'9') { if(ch=='-') f = -1 ; ch = getchar() ; } 
    21     while(ch>='0'&&ch<='9')  { x = x*10 + ch-48 ; ch = getchar() ; } 
    22     return x*f ;  
    23 }
    24 
    25 int main() 
    26 {
    27     n = read() ; 
    28     for(int i=1;i<=n;i++ ) a[ i ] = read() ; 
    29     for(int j=1;j<maxm;j++) 
    30     {
    31         for(int i=1;i<=n;i++) 
    32         {
    33             if(a[ i ]==j) f[ i ][ j ] = i+1 ; 
    34             else f[ i ][ j ] = f[ f[ i ][ j-1 ] ][j-1] ; 
    35             if(f[ i ][ j ]) ans=max(ans,j) ; 
    36         }
    37     }
    38     printf("%d
    ",ans) ; 
    39     return 0 ; 
    40 }
  • 相关阅读:
    java的instanceof简单使用
    PHP中return,exit,die的区别
    C#调用Dll文件中方法的简单应用
    C#的托管和非托管的简单理解
    对象造型(引用类型转换)
    面向对象3大特性的简单理解
    css3自定义滚动条背景透明
    console.time方法与console.timeEnd方法
    IE8 input X 去掉文本框的叉叉和密码输入框的眼睛图标
    JavaSript模块规范
  • 原文地址:https://www.cnblogs.com/third2333/p/7015805.html
Copyright © 2020-2023  润新知