M - Walking Plan HDU - 6331
Posted lordxx
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了M - Walking Plan HDU - 6331相关的知识,希望对你有一定的参考价值。
分块+floyd
令dp[i][j][k]表示i到j恰好k条路经的最小权值。那么就有:dp[i][j][k]=min{dp[i][p][k-1]+dp[p][j][1]}我们可以预处理出前100条路径的dp值。然后考虑大范围转移,对dp[i][j][100]做一次floyd转移到200,再做一次转移到300,以此类推。
就可以求得,从j到j恰好k条路径的最小权值。
题目要求至少k条路径。那么对于小范围1~100的dp,我们从大往小,取min值,便可以表示从i到j至少k条路经的最小权值。对于大范围,dp[i][j][k*100],因为1~100的值我们已经更新过了,所以使用1~100来更新每一个k*100,便可以表示,至少k*100条路经,但少于(k+1)*100条路径的最小权值。查询的时候优先查询100的倍数,剩下的值通过1~100补全。
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<bitset>
#include<map>
//#include<regex>
#include<cstdio>
#pragma GCC optimize(2)
#define up(i,a,b) for(int i=a;i<b;i++)
#define dw(i,a,b) for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
char ch = getchar(); ll x = 0, f = 1;
while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
int T;
int n, m, q;
const int mod = 1e9 + 7;
struct mat {
int a[55][55];
int n;
void init(int n)
{
this->n = n;
upd(i, 0, n)upd(j, 0, n)a[i][j] = mod;
}
}dp_sm[105], dp_big[105];
mat floyd(mat dp1, mat dp2, mat dp3)
{
mat res; res.init(n);
int len = dp1.n;
upd(i, 1, len)upd(j, 1, len)res.a[i][j] = min(res.a[i][j], dp3.a[i][j]);
upd(k, 1, len)
{
upd(i, 1, len)
{
upd(j, 1, len)
{
if (dp1.a[i][k] == mod || dp2.a[k][j] == mod)continue;
res.a[i][j] = min(res.a[i][j], dp1.a[i][k] + dp2.a[k][j]);
}
}
}
return res;
}
int main()
{
T = read();
while (T--)
{
n = read(), m = read();
int u, v; int w;
upd(i, 0, 100)dp_sm[i].init(n), dp_big[i].init(n);
upd(i, 0, n)dp_sm[0].a[i][i] = dp_big[0].a[i][i] = 0;
upd(i, 1, m)
{
u = read(), v = read(), w = read();
dp_sm[1].a[u][v] = min(dp_sm[1].a[u][v], w);
}
upd(i, 0, 100)
{
dp_sm[i + 1] = floyd(dp_sm[1], dp_sm[i], dp_sm[i + 1]);
}
//upd(i, 1, n) { upd(j, 1, n) { printf("%d ", dp_sm[1].a[i][j]); }cout << endl; }
dp_big[1] = dp_sm[100];
upd(i, 0, 100)
{
dp_big[i + 1] = floyd(dp_big[1], dp_big[i], dp_big[i + 1]);
}
dwd(k, 99, 1)
{
upd(i, 1, n)upd(j, 1, n)dp_sm[k].a[i][j] = min(dp_sm[k + 1].a[i][j], dp_sm[k].a[i][j]);//反向取,表示至少
}
//upd(i, 1, n) { upd(j, 1, n) { printf("%lld ", dp_sm[1].a[i][j]); }cout << endl; }
upd(i, 1, 100)
{
dp_big[i] = floyd(dp_big[i], dp_sm[1], dp_big[i]);
}
q = read();
while (q--)
{
u = read(), v = read(), w = read();
//cout << "*" << endl;
int md = w % 100;
int quan = w / 100;
int ans = mod;
// upd(i, 1, n) { upd(j, 1, n) { printf("%lld ", dp_sm[1].a[i][j]); }cout << endl; }
upd(k, 1, n)
{
//cout <<"k"<<k<<" "<< dp_sm[md].a[k][v] << endl;
ans = min(ans, dp_big[quan].a[u][k] + dp_sm[md].a[k][v]);
}
if (ans == mod)printf("-1
");
else printf("%d
", ans);
}
}
return 0;
}
以上是关于M - Walking Plan HDU - 6331的主要内容,如果未能解决你的问题,请参考以下文章
2018HDU多校训练-3-Problem M. Walking Plan
POJ 3162 Walking Race 树形dp 优先队列