【Educational Codeforces Round 58(Rated for Div.2)F.Trucks and Cities】DP+単調キュー最適化
25338 ワード
タイトルリンク
F. Trucks and Cities
に言及
n都市がx軸上にあり、m台のトラックがあり、各トラックには4つの属性があり、それぞれ開始都市s、終了都市f、1キロ当たり燃料消費c、および給油可能回数rである.給油トラックの油量が満タンになるたびに、トラックの油量はVで、すべてのトラックの初期油量は満タンになります.すべてのトラックを始点から終点までの最小油量Vを求める.
2 < = n < = 400 , 1 < = m < = 250000 2<=n<=400,1<=m<=250000 2<=n<=400,1<=m<=250000 1 < = a i < = 1 0 9 , a i < a i + 1 1<=a_i<=10^9,a_iまず暴力的なn 4 n^4 n 4のやり方を考えます.d p[i][j][k]dp[i][j][k]dp[i][j][k]をi i iからj j j休憩k回に到達する最小間隔とする.d p [ i ] [ j ] [ k ] = min j − 1 l = i + 1 ( max ( d p [ i ] [ l ] [ k − 1 ] , a [ j ] − a [ l ] ) ) dp\left[ i\right]\left[ j\right]\left[ k\right] =\underset{l=i+1}{\overset{j-1}{\min}}\left(\max\left( dp\left[ i\right]\left[ l\right]\left[ k-1\right] ,a\left[ j\right] -a\left[ l\right]\right)\right) dp[i][j][k]=l=i+1 minj−1(max(dp[i][l][k−1],a[j]−a[l]))コード
まず1次元をスクロールすることができ,その後max(d p[i][l][k−1],a[j]−a[l])maxleft(dpleft[iright]left[lright]left[lright],aleft[jright]−aleft[lright]right)max(dp[i][l][k−1],a[j]−a[l])これは決定の単調性を満たすことが分かった.単調なキューメンテナンスが必要で、複雑さはn 3 n^3 n 3になります.
コード#コード#
F. Trucks and Cities
に言及
n都市がx軸上にあり、m台のトラックがあり、各トラックには4つの属性があり、それぞれ開始都市s、終了都市f、1キロ当たり燃料消費c、および給油可能回数rである.給油トラックの油量が満タンになるたびに、トラックの油量はVで、すべてのトラックの初期油量は満タンになります.すべてのトラックを始点から終点までの最小油量Vを求める.
2 < = n < = 400 , 1 < = m < = 250000 2<=n<=400,1<=m<=250000 2<=n<=400,1<=m<=250000 1 < = a i < = 1 0 9 , a i < a i + 1 1<=a_i<=10^9,a_i
#include
#include
#include
using namespace std;
typedef long long ll;
const int maxn = 405;
int dp[maxn][maxn][maxn]; // dp[i][j][k] i j k 。
int a[maxn];
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
dp[i][j][0]=a[j]-a[i];
for(int k=1;k<=n;k++)
{
dp[i][j][k]=a[j]-a[i];
for(int l=i+1;l<j;l++)
{
dp[i][j][k]=min(dp[i][j][k],max(dp[i][l][k-1],a[j]-a[l]));
}
}
}
}
ll ans=0;
for(int i=1;i<=m;i++)
{
int s,f,c,r;
scanf("%d%d%d%d",&s,&f,&c,&r);
ans=max(ans,1LL*dp[s][f][r]*c);
}
printf("%lld
",ans);
return 0;
}
まず1次元をスクロールすることができ,その後max(d p[i][l][k−1],a[j]−a[l])maxleft(dpleft[iright]left[lright]left[lright],aleft[jright]−aleft[lright]right)max(dp[i][l][k−1],a[j]−a[l])これは決定の単調性を満たすことが分かった.単調なキューメンテナンスが必要で、複雑さはn 3 n^3 n 3になります.
コード#コード#
#include
#include
#include
using namespace std;
typedef long long ll;
const int maxn = 405;
int dp[maxn][maxn]; // dp[i][j][k] i j k 。
int a[maxn];
int pos[maxn];
struct data
{
int f,c,r;
data(){}
data(int ff,int cc,int rr)
{
f=ff;
c=cc;
r=rr;
}
};
vector<data> G[maxn];
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=m;i++)
{
int s,f,c,r;
scanf("%d%d%d%d",&s,&f,&c,&r);
G[s].push_back(data(f,c,r));// s
}
ll ans=0;
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
dp[j][0]=a[j]-a[i];
int pos=0;
for(int k=1;k<=n;k++)
{
dp[j][k]=a[j]-a[i];
while(pos+1<=j&&dp[pos+1][k-1]<a[j]-a[pos+1]) pos++;// DP
dp[j][k]=min(dp[j][k],min(a[j]-a[pos],dp[pos+1][k-1]));
}
}
for(int j=0;j<G[i].size();j++)
{
int f=G[i][j].f;
int c=G[i][j].c;
int r=G[i][j].r;
ans=max(ans,1LL*dp[f][r]*c);
}
}
printf("%lld
",ans);
return 0;
}