BZOJ1261: [SCOI2006]zh_tree
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1261
区间dp,f[l][r]=min(f[l][now-1]+f[now+1][r]+c*f[i]),然后最后再加上k*(sum[r]-sum[l-1])/sum[n]
#include<cstring> #include<cstdio> #include<iostream> #include<algorithm> #include<cmath> #include<queue> #define rep(i,l,r) for (int i=l;i<=r;i++) #define down(i,l,r) for (int i=l;i>=r;i--) #define clr(x,y) memset(x,y,sizeof(x)) #define inf int(1e9) #define maxn 31 #define mm 30031 using namespace std; int a[maxn],s,n; double sum[maxn],f[maxn],k,c,d[maxn][maxn]; int vis[maxn][maxn]; int read(){ int x=0,f=1; char ch=getchar(); while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();} while (isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();} return x*f; } double dfs(int l,int r){ if (l>r) return 0; if (vis[l][r]) return d[l][r]; if (!vis[l][r]) vis[l][r]=1; d[l][r]=1e20; rep(i,l,r) d[l][r]=min(d[l][r],dfs(l,i-1)+dfs(i+1,r)+c*(sum[i]-sum[i-1])/sum[n]); d[l][r]+=k*(sum[r]-sum[l-1])/sum[n]; return d[l][r]; } int main(){ n=read(); scanf("%lf%lf",&k,&c); rep(i,1,n) { double x; scanf("%lf",&x); sum[i]=sum[i-1]+x; } dfs(1,n); printf("%.3lf\n",d[1][n]); return 0; }