agc036D

题目大意

题解

过于巧妙

关键点:无负环=差分约束有解

由于有i->i+1的0边,所以fi>=fi+1,又因为边的绝对值不超1,所以fi<=(fi+1)+1

设f[i][j]表示当前f相同的段是[j+1,i],枚举下一段结尾k转移,负边不能连同一个块,正边只能连同块和相邻两个块的

code

#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define min(a,b) (a<b?a:b)
#define max(a,b) (a>b?a:b)
#define ll long long
//#define file
using namespace std;

ll a[502][502],b[502][502],f[501][501],ans,sum;
int n,i,j,k,l;

int main()
{
	#ifdef file
	freopen("agc036d.in","r",stdin);
	#endif
	
	scanf("%d",&n);
	fo(i,1,n)
	{
		fo(j,1,n)
		if (i!=j)
		scanf("%lld",&a[i][j]),b[i][j]=a[i][j]*(i>j),a[i][j]*=(i<j);
	}
	fo(i,1,n) fo(j,1,n) a[i][j]+=a[i-1][j]+a[i][j-1]-a[i-1][j-1],b[i][j]+=b[i-1][j]+b[i][j-1]-b[i-1][j-1];
	
	memset(f,128,sizeof(f));
	fo(i,1,n)
	{
		f[i][0]=b[i][i];
		fo(j,0,i-1)
		{
			fo(k,i+1,n)
			f[k][i]=max(f[k][i],f[i][j]+(a[i][k]-a[i][i])+((b[k][k]-b[i][k])-(b[k][j]-b[i][j])));
		}
	}
	
	ans=0;
	fo(i,0,n-1) ans=max(ans,f[n][i]);
	ans=a[n][n]+b[n][n]-ans;
	printf("%lld
",ans);
	
	fclose(stdin);
	fclose(stdout);
	return 0;
}
原文地址:https://www.cnblogs.com/gmh77/p/13714906.html