您的位置:首页 > 其它

BZOJ 2165 大楼 类矩阵乘法/倍增Floyd 二进制判断状态

2015-12-02 19:25 423 查看
给出n条有向边,要求从点1走到标号≥m的点的最短距离。

一看和倍增Floyd很像。

令dp[p][i][j]表示坐了p次电梯从i到j的最大上升高度。

那么dp[0]就是题目给定的w。

有dp[p][i][j]=max{dp[p/2][i][k]+dp[p/2][k][j]}

发现dp[p]可以倍增得到。

当dp[p][1][?]>=m时即可停止。

倍增完后按照正常想法利用就是通过二进制位判断状态即可。

对于答案的某个位i(1<<i),dp[i]乘上当前答案的状态得到新状态,如果没有达到最终状态就加入答案(把第i位改为1,即用了dp[i])。

从高位向低位贪心。最后要加1。

#include <cstdio>
#include <cstring>
#include <algorithm>
#define inf (1ll<<62)
#define FOR(i,j,k) for(int i=j;i<=k;i++)
using namespace std;
typedef long long ll;
int n; ll m;
struct Matrix {
ll v[101][101];
Matrix() { memset(v, 0, sizeof v); }
ll *operator [](int x) { return v[x]; }
friend Matrix operator *(Matrix a, Matrix b) {
Matrix c;
FOR(i,1,n) FOR(j,1,n) {
c[i][j] = -inf;
FOR(k,1,n) c.v[i][j] = max(c[i][j], a[i][k] + b[k][j]);
if (c[i][j] > m) c[i][j] = m;
}
return c;
}
} f[100];
bool check(Matrix x) {
FOR(i,1,n) if (x[1][i] >= m) return true;
return false;
}
int main() {
int kase, cnt;
scanf("%d", &kase);
while (kase--) {
scanf("%d%lld", &n, &m);
FOR(i,1,n) FOR(j,1,n) {
scanf("%lld", &f[0][i][j]);
if (f[0][i][j] == 0) f[0][i][j] = -inf;
}
for (cnt = 0; ; ) {
f[cnt + 1] = f[cnt] * f[cnt];
if (check(f[++cnt])) break;
}
Matrix t = f[0];
ll ans = 1;
for (int i = cnt; i >= 0; i--) {
Matrix x = t * f[i];
if (!check(x)) {
t = x;
ans += 1ll << i;
}
}
printf("%lld\n", ans + 1);
}
return 0;
}

2165: 大楼

Time Limit: 40 Sec  Memory Limit: 259 MB
Submit: 632  Solved: 227

[Submit][Status][Discuss]

Description

xz是一个旅游爱好者,这次他来到了一座新的城市。城市中央有一幢高耸入云的大楼。这幢楼到底有多少层呢?据说和非负整数的个数是一样多的。xz想爬上这座大楼来观赏新城市的全景。这幢大楼的楼层从下至上用从小到大的非负整数编号。每层楼有n个房间,用1到n的正整数编号。楼层之间用电梯连接,电梯只能上行,不能下行或者同层移动。(下楼一般自行解决)电梯用(u,v,w)的形式给出,表示对于任意正整数i,有第i层的房间u到第i+w层的房间v有一部电梯。电梯只能从起点开往终点,不能中途停留。 xz想要观赏城市全景,至少需要登上第m层楼,即最终需要到达的楼层数≥m。由于乘坐电梯要缴纳高额的费用,而如果花销太大回家就没法报账了,xz希望乘坐电梯的次数最少。现在xz在第0层的1号房间,你需要求出这个最少的乘坐次数。

Input

第一行包含一个正整数T,表示数据的组数。接下来的数据分为T个部分。每个部分第一行包含两个正整数n和m,意义见题目描述。接下来n行,每行包含n个非负整数。这n行中,第i行第j个数为Wi,j,如果wi,j非零,则表示有电梯(i,j,Wi,j)。同一行各个数之间均用一个空格隔开。

Output

对于每组数据,输出一行一个正整数,最少的乘坐次数。

Sample Input

2

6 147

0 1 0 50 0 0

0 0 1 0 0 0

20 0 0 0 0 0

0 0 0 0 1 50

0 0 0 8 0 0

0 0 0 0 0 3

6 152

0 1 0 50 0 0

0 0 1 0 0 0

20 0 0 0 0 0

0 0 0 0 1 50

0 0 0 8 0 0

0 0 0 0 0 3

Sample Output

9

10

【样例说明】

第一组数据中,使用电梯的顺序为1→2→3→1→2→3→1→4→6→6;第二组数据中,使用电梯的顺序为1→2→3→1→2→3→1→4→5→4→6。第二组数据最后到达了153层,但是没有更短的路径使得恰好到达152层,因此答案为10。

HINT

有如下几类具有特点的数据: 1、有10%的数据所有的n=2; 2、有20%的数据m≤3000; 3、有20%的数据对于满足1≤i,j≤n的整数i和j,若wi,j≠0,则有wi,j≥1015; 4、有30%的数据所有的n=40。以上各类数据均不包含其他类数据。对于所有数据T=5,1≤n≤100,1≤m≤1018;对于满足1≤i,j≤n的整数i和j,有0≤wi,j≤1018。数据保证能够到达m层或更高的楼层。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: