题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=2829
思路:大神地址:http://www.tuicool.com/articles/nMzAzi6
四边形不等式:http://wenku.baidu.com/view/be418243a8956bec0975e3bf.html
待写代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <queue> #include <stack> #include <map> #include <cstring> #include <climits> #include <cmath> #include <cctype> const int inf = 0x3f3f3f3f;//1061109567 typedef long long LL; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 using namespace std; LL dp[1010][1010],cost[1010][1010]; int a[1010]; int s[1010][1010]; int main() { int n,m; while(scanf("%d%d",&n,&m)) { if(m + n == 0) break; for(int i=1; i<=n; i++) scanf("%d",&a[i]); /*memset(cost,0,sizeof(cost)); for(int i=1; i<=n; i++) { for(int j=i+1; j<=n; j++) { cost[i][j] = cost[i][j-1]; for(int k=i; k<=j; k++) { cost[i][j] += a[j] * a[k]; } } }*/ for(int i=1; i<=n; i++) { LL sum = 0; cost[i][i] = 0; for(int j=i+1; j<=n; j++) { sum += a[j-1]; cost[i][j] = cost[i][j-1] + sum * a[j]; } } for(int i=1; i<=n; i++) { dp[0][i] = cost[1][i]; s[0][i] = 0; s[i][n+1] = n; } for(int i=1; i<=m; i++) { for(int j=n; j>=1; j--)//这层循环是倒着来着,和01背包一个道理 { dp[i][j] = cost[i][j]; for(int k=s[i-1][j]; k<=s[i][j+1]; k++) { dp[i][j] = min(dp[i][j],dp[i-1][k]+cost[k+1][j]); s[i][j] = k; } } } printf("%I64d\n",dp[m][n]); } return 0; }
超时代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <queue> #include <stack> #include <map> #include <cstring> #include <climits> #include <cmath> #include <cctype> const int inf = 0x3f3f3f3f;//1061109567 typedef long long LL; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 using namespace std; LL dp[1010][1010],cost[1010][1010]; int a[1010]; int main() { int n,m; while(scanf("%d%d",&n,&m)) { if(m + n == 0) break; for(int i=1; i<=n; i++) scanf("%d",&a[i]); /*memset(cost,0,sizeof(cost)); for(int i=1; i<=n; i++) { for(int j=i+1; j<=n; j++) { cost[i][j] = cost[i][j-1]; for(int k=i; k<=j; k++) { cost[i][j] += a[j] * a[k]; } } }*/ for(int i=1; i<=n; i++) { LL sum = 0; cost[i][i] = 0; for(int j=i+1; j<=n; j++) { sum += a[j-1]; cost[i][j] = cost[i][j-1] + sum * a[j]; } } for(int i=1; i<=n; i++) { dp[0][i] = cost[1][i]; } for(int i=1; i<=m; i++) { for(int j=n; j>=1; j--)//这层循环是倒着来着,和01背包一个道理 { dp[i][j] = cost[i][j]; for(int k=i; k<j; k++) { dp[i][j] = min(dp[i][j],dp[i-1][k]+cost[k+1][j]); } } } printf("%I64d\n",dp[m][n]); } return 0; }