Atcoder agc036D

该博客讨论了Atcoder AGC036D问题,涉及无负环路径的设定。文章指出,在给定条件下,可以为每个点分配一个距离值,满足特定的边界条件。为了确保距离合法,对于相邻点,存在关于边权的限制。博主通过计数策略,定义状态F[i][j]表示前i个点中有一段连续的点具有相同的距离值,并不等于前一个点的距离值。通过对k的枚举,博主提出了O(N^3)的时间复杂度解决方案。
摘要由CSDN通过智能技术生成

没有负环可以理解为能够给第 i i i个点一个距离值 d i d_i di。由于 i i i i + 1 i+1 i+1 0 0 0边,因此 d i ≥ d i + 1 d_i\geq d_{i+1} didi+1,且由于边权绝对值不超过 1 1 1,因此 d i ≤ d i + 1 + 1 d_i\leq d_{i+1}+1 didi+1+1。为了使距离值合法,对于 j < i j<i j<i,若 d j = d i d_j=d_i dj=di,不能有 − 1 -1 1的边,若 d j > d i + 1 d_j>d_i+1 dj>di+1,不能有 1 1 1的边,且若 d i = d i − 1 − 1 d_i=d_{i-1}-1 di=di11,必须有 d j = d i + 1 d_j=d_i+1 dj=di+1 i i i − 1 -1 1的边。
考虑计数,设 F [ i ] [ j ] F[i][j] F[i][j]表示考虑到 i i i d j = d j + 1 = . . . = d i d_j=d_{j+1}=...=d_i dj=dj+1=...=di d i ≠ d j − 1 d_i\neq d_{j-1} di=dj1,转移枚举一个 k > i k>i k>i,使得 d i + 1 = d i + 2 = . . . = d k = d i − 1 d_{i+1}=d{i+2}=...=d_k=d_i-1 di+1=di+2=...=dk=di1,乘上贡献即可。
时间复杂度 O ( N 3 ) \mathcal O(N^3) O(N3)

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

inline void update(ll &x,ll y) {
  x=max(x,y);
}

int num[505][505];

ll sum1[505][505],sum2[505][505];

void pre(int n) {
  for(int i=0;i<=n;i++)
    for(int j=i+1;j<=n;j++) sum1[i][j]=sum1[i][j-1]+num[i][j];
  for(int i=n;i>=0;i--)
    for(int j=i+1;j<=n;j++) sum1[i][j]=sum1[i+1][j]+sum1[i][j];
  for(int i=0;i<=n;i++)
    for(int j=i+1;j<=n;j++) sum2[i][j]=sum2[i][j-1]+num[j][i];
  for(int i=n;i>=0;i--)
    for(int j=i+1;j<=n;j++) sum2[i][j]=sum2[i+1][j]+sum2[i][j];
}

ll f[505][505];

void dp(int n) {
  for(int i=0;i<n;i++)
    for(int j=0;j<=i;j++)
      for(int k=i+1;k<=n;k++) 
        update(f[k][i],f[i][j]+sum1[0][k]-sum1[0][i]-sum1[i+1][k]+sum2[j+1][k]-sum2[j+1][i]);
}

int main() {
  int n;
  scanf("%d",&n);
  ll s=0;
  for(int i=1;i<=n;i++)
    for(int j=1;j<=n;j++)
      if (i!=j) {
	    scanf("%d",&num[i][j]);
	    s+=num[i][j];
	  }
  pre(n);
  dp(n);
  ll ans=0;
  for(int i=0;i<=n;i++) update(ans,f[n][i]);
  printf("%lld\n",s-ans);
  return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值