首先如果不考虑数据范围的话,因为每一层都是等效的,所以我们可以用w[i][j][k]来表示在某一层的j位置,称作i次电梯到k位置,最多上升多少层,那么我们可以比较容易的写出转移,因为m十分大,i可能与m同阶,所以我们不能直接枚举i,这样我们考虑二进制的思想,w[2^p][j][k]表示用了2^p次电梯,最多上升的层数,那么这样我们可以直接由w[2^p-1][j][mid]和w[2^p-1][mid][k]转移过来,但是这样求出来的是我们最少用2^p次可以到达m层,最后的答案可能会比这个小,那么我们可以逐位的判断答案,是否可以通过减少某一位的1仍能达到m层,那样我们这个1就可以去掉,也就是不断地更新答案,这样就好了。

  反思:因为最后的答案可能是2^p,但是这样逐位的判断不能讲答案加回2^p,所以需要将答案的初值设为1.

/**************************************************************
    Problem: 2165
    User: BLADEVIL
    Language: C++
    Result: Accepted
    Time:20640 ms
    Memory:11392 kb
****************************************************************/
 
//By BLADEVIL
#include <cstdio>
#include <cstring>
#include <algorithm>
#define maxn 110
#define maxx 60
#define LL long long
 
using namespace std;
 
LL g[maxn][maxn][maxn],p[maxn][maxn],q[maxn][maxn];
LL n,m;
 
void solve() {
    LL t,ans=;
    scanf("%d%lld",&n,&m);
    memset(g,,sizeof(g));
    for (int i=;i<=n;i++)
        for (int j=;j<=n;j++) {
            t=;
            scanf("%lld",&g[][i][j]),g[][i][j]=min(g[][i][j],m);
            if (i==) t=max(t,g[][i][j]);
        }
    if (t==m) {
        printf("1\n");
        return;
    }
    int k;
    for (k=;k<=maxx;k++) {
        t=;
        for (int i=;i<=n;i++)
            for (int j=;j<=n;j++) {
                for (int mid=;mid<=n;mid++)
                    if (g[k-][i][mid]&&g[k-][mid][j])
                        g[k][i][j]=max(g[k][i][j],g[k-][i][mid]+g[k-][mid][j]);
                g[k][i][j]=min(g[k][i][j],m);
                if (i==) t=max(t,g[k][i][j]);
            }
        if (t==m) break;
    }
    memcpy(p,g[--k],sizeof(p));
    for (ans+=1LL<<k--;k>=;k--) {
        memset(q,,sizeof(q));
        t=;
        for (int i=;i<=n;i++)
            for (int j=;j<=n;j++) {
                for (int mid=;mid<=n;mid++)
                    if (p[i][mid]&&g[k][mid][j])
                        q[i][j]=max(q[i][j],p[i][mid]+g[k][mid][j]);
                q[i][j]=min(q[i][j],m);
                if (i==) t=max(t,q[i][j]);
            }
        if (t!=m) {
            ans+=1LL<<k;
            memcpy(p,q,sizeof(p));
        }
    }
    printf("%lld\n",ans);
}
 
int main() {
    int test;
    scanf("%d",&test);
    while (test--) solve();
    return ;
}

bzoj 2165 DP的更多相关文章

  1. [BZOJ 2165] 大楼 【DP + 倍增 + 二进制】

    题目链接:BZOJ - 2165 题目分析: 这道题我读了题之后就想不出来怎么做,题解也找不到,于是就请教了黄学长,黄学长立刻秒掉了这道题,然后我再看他的题解才写出来..Orz 使用 DP + 倍增 ...

  2. bzoj 3622 DP + 容斥

    LINK 题意:给出n,k,有a,b两种值,a和b间互相配对,求$a>b$的配对组数-b>a的配对组数恰好等于k的情况有多少种. 思路:粗看会想这是道容斥组合题,但关键在于如何得到每个a[ ...

  3. BZOJ - 1003 DP+最短路

    这道题被马老板毒瘤了一下,TLE到怀疑人生 //然而BZOJ上妥妥地过了(5500ms+ -> 400ms+) 要么SPFA太玄学要么是初始化block被卡到O(n^4) 不管了,不改了 另外D ...

  4. BZOJ 2431 & DP

    题意:求逆序对数量为k的长度为n的排列的个数 SOL: 显然我们可以对最后一位数字进行讨论,判断其已经产生多少逆序对数量,然后对于前n-1位同样考虑---->每一个长度的排列我们都可以看做是相同 ...

  5. bzoj 1791 DP

    首先对于一棵树我们可以tree_dp来解决这个问题,那么对于环上每个点为根的树我们可以求出这个树的一端为根的最长链,并且在tree_dp的过程中更新答案.那么我们对于环,从某个点断开,破环为链,然后再 ...

  6. bzoj 1592 dp

    就是dp啊 f[i][j]表示到第i位,最后一位高度是j的最小花费 转移::f[i][j]=minn(f[i-1][k])+abs(a[i]-num[j]);(k<=j) #include< ...

  7. BZOJ 1207 DP

    打一次鼹鼠必然是从曾经的某一次打鼹鼠转移过来的 以打每一个鼹鼠时的最优解为DP方程 #include<iostream> #include<cstdio> #include&l ...

  8. bzoj 1925 dp

    思路:dp[ i ][ 0 ]表示第一个是山谷的方案,dp[ i ][ 1 ]表示第一个是山峰的方案, 我们算dp[ x ][ state ]的时候枚举 x 的位置 x 肯定是山峰, 然后就用组合数算 ...

  9. bzoj 1820 dp

    最普通dp要4维,因为肯定有一个在上一个的位置,所以可以变为3维,然后滚动数组优化一下. #include<bits/stdc++.h> #define LL long long #def ...

随机推荐

  1. 一个比较典型的WMI查询

    Get-WmiObject win32_bios -ComputerName server1, server2 | Format-Table ` @{n='Hostname';e={$_.__serv ...

  2. Android出现:Your project path contains non-ASCII characters.

    导入Project的出现: Error:(1, 0) Your project path contains non-ASCII characters. This will most likely ca ...

  3. 如何取得dbgrid中未保存(post)的值(50分)

    比如说处在编辑状态时,想取得当前记录值 Dataset.fields[0].Value 就是当前值:Dataset.fields[0].OldValue 就是原始值. 呵呵,我指得是在编辑时,就是按键 ...

  4. 在js中对日期的加减法

    以在某个日期上加减天数来说,其实只要调用Date对象的setDate()函数就可以了,对月份来说,使用setMonth(),具体方法如下:      function addDate(date, da ...

  5. Qt Pro文件与Qt模块启用

    看qt论坛中经常有人忘记 QT+=network 等语句.随便写写吧,或许对他人有帮助. 一.从哪开始呢 不妨先看个例子吧: #include <QtCore/QCoreApplication& ...

  6. BZOJ 2303 方格染色(带权并查集)

    要使得每个2*2的矩形有奇数个红色,如果我们把红色记为1,蓝色记为0,那么我们得到了这2*2的矩形里的数字异或和为1. 对于每个方格则有a(i,j)^a(i-1,j)^a(i,j-1)^a(i-1,j ...

  7. 【bzoj4922】[Lydsy六月月赛]Karp-de-Chant Number 贪心+背包dp

    题目描述 给出 $n$ 个括号序列,从中选出任意个并将它们按照任意顺序连接起来,求以这种方式得到匹配括号序列的最大长度. 输入 第一行包含一个正整数n(1<=n<=300),表示括号序列的 ...

  8. [SDOI2015]约数个数和 莫比乌斯反演

    ---题面--- 题解: 为什么SDOI这么喜欢莫比乌斯反演,,, 首先有一个结论$$d(ij) = \sum_{x|i}\sum_{y|j}[gcd(x, y) == 1]$$为什么呢?首先,可以看 ...

  9. [ZJOI2010]数字计数 数位DP

    最近在写DP,今天把最近写的都放上来好了,,, 题意:给定两个正整数a和b,求在[a,b]中的所有整数中,每个数码(digit)各出现了多少次. 首先询问的是一个区间,显然是要分别求出1 ~ r ,1 ...

  10. BZOJ3076 & 洛谷3081:[USACO2013 MAR]Hill Walk 山走——题解

    http://www.lydsy.com/JudgeOnline/problem.php?id=3076 https://www.luogu.org/problemnew/show/P3081#sub ...