矩阵连乘源码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <queue> #include <stack> #include <map> #include <cstring> #include <climits> #include <cmath> #include <cctype> typedef long long ll; using namespace std; int m[110][110]; int a[110]; int n; int course(int i,int j) { if(m[i][j] != -1)//已经算出来这个值,直接返回 { return m[i][j]; } if(i == j) { return 0; } if(i == j-1) { m[i][j] = a[i] * a[i+1] * a[i+2]; return m[i][j]; } int u = course(i,i) + course(i+1,j) + a[i] * a[i+1] * a[j+1]; int k,t; for(k=i+1; k<j; k++) { t = course(i,k) + course(k+1,j) + a[i] * a[k+1] * a[j+1]; if(t < u) u = t; } m[i][j] = u; return m[i][j]; } int main() { int i; while(scanf("%d",&n) != EOF) { memset(m,-1,sizeof(m));//设置备忘录。刚开始初始值为-1 for(i=1; i<=n+1; i++) { scanf("%d",&a[i]); } int sum = course(1,n); printf("%d\n",sum); } return 0; }
题目地址:http://acm.nyist.net/JudgeOnline/problem.php?pid=536
思路:在模板上的简单改动
AC代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <queue> #include <stack> #include <map> #include <cstring> #include <climits> #include <cmath> #include <cctype> typedef long long ll; using namespace std; int m[110][110]; int a[110]; int n; int course(int i,int j) { if(m[i][j] != -1)//已经算出来这个值,直接返回 { return m[i][j]; } if(i == j) { return 0; } if(i == j-1) { m[i][j] = a[i] * a[i+1] * a[i+2]; return m[i][j]; } int u = course(i,i) + course(i+1,j) + a[i] * a[i+1] * a[j+1]; int k,t; for(k=i+1; k<j; k++) { t = course(i,k) + course(k+1,j) + a[i] * a[k+1] * a[j+1]; if(t < u) u = t; } m[i][j] = u; return m[i][j]; } int main() { int i; while(scanf("%d",&n) != EOF) { int b; memset(m,-1,sizeof(m));//设置备忘录。刚开始初始值为-1 for(i=1; i<=n-1; i++) { scanf("%d%d",&a[i],&b); } scanf("%d%d",&a[n],&a[n+1]); int sum = course(1,n); printf("%d\n",sum); } return 0; }
题目地址:http://acm.nyist.net/JudgeOnline/problem.php?pid=737
从最中间的一条线向右上角斜着算,和矩阵连乘类似,可以用四边形不等式优化
四边形不等式详解地址:http://blog.163.com/dqx_wl/blog/static/2396821452015111133052112/
AC代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <queue> #include <stack> #include <map> #include <cstring> #include <climits> #include <cmath> #include <cctype> typedef long long ll; using namespace std; int a[210]; int dp[210][210]; int s[210][210]; int main() { int n,i,j,k,r; while(scanf("%d",&n) != EOF) { for(i=1; i<=n; i++) { scanf("%d",&a[i]); } for(i=1; i<=n; i++) { s[i][i] = a[i]; for(j=i+1; j<=n; j++) { s[i][j] = s[i][j-1] + a[j];//得出合并区间i到j的结果 } } for(r=2; r<=n; r++) { for(i=1; i<=n-r+1; i++) { j = i + r - 1; dp[i][j] = INT_MAX; for(k=i; k<j; k++) { if(dp[i][j] > dp[i][k] + dp[k+1][j]) { dp[i][j] = dp[i][k] + dp[k+1][j]; } } dp[i][j] += s[i][j]; } } printf("%d\n",dp[1][n]); } return 0; }
题目地址:点击打开链接
思路:注意数组是从a+1开始存的
AC代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <queue> #include <stack> #include <map> #include <cstring> #include <climits> #include <cmath> #include <cctype> typedef long long ll; using namespace std; char a[110]; int dp[110][110]; int main() { int i,j,k,l; while(scanf("%s",a+1)) { memset(dp,0,sizeof(dp)); if(!strcmp(a+1,"end")) break; int len = strlen(a+1); for(l=2; l<=len; l++) { for(i=1; i<=len-l+1; i++) { j = i + l - 1; if((a[i] == '(' && a[j] == ')') || ( a[i] == '[' && a[j] == ']')) { dp[i][j] = dp[i+1][j-1] + 2; } for(k=i; k<j; k++) { dp[i][j] = max(dp[i][j],dp[i][k] + dp[k+1][j]); } } } printf("%d\n",dp[1][len]); } return 0; }