主要大区间化为小区间……
先小区间求值……
状态转移方程 f(i,j) = min{ f(i,k) + f(k+1,j) + p[i-1]p[k]p[j] };
poj 1651 http://poj.org/problem?id=1651
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <cstdlib> const int MAXN = 100 + 10; const double ESP = 10e-8; const double Pi = atan(1.0) * 4; const int INF = 0xfffffff; const int MOD = 10000007; using namespace std; int n; int dp[MAXN][MAXN]; int c[MAXN]; void multiplication(){ for(int i = 0;i < n;i++){ dp[i][i] = 0; } for(int l = 2;l < n;l++){ for(int i = 1;i < n-l+1;i++){ int j = i+l-1; dp[i][j] = INF; for(int k = i;k < j;k++){ int tmp = dp[i][k] + dp[k+1][j] + c[i-1] * c[k] * c[j]; dp[i][j] = min(dp[i][j],tmp); } } } } int main(){ //freopen("input.txt","r",stdin); scanf("%d",&n); for(int i = 0;i < n;i++){ scanf("%d",&c[i]); } multiplication(); printf("%d\n",dp[1][n-1]); return 0; }
poj 1179 http://poj.org/problem?id=1179
大致题意:
给你一个环,点是数字,边是运算,你断掉其中一条边之后,然后可以把相连的两个点经边的运算合并成一个点,求最大值
解题思路,枚举断的点然后进行矩阵相乘。
题解……1 我抄都抄不会的代码…… 抄来代码就是运行不对…… Orz ……http://m.blog.csdn.net/blog/u012962816/26822959
题解……2 http://www.tuicool.com/articles/Jj2Avi
在第一个自己笨到抄不对的时候,参考了题解2
然后从新自己写了一下……
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <cstdlib> const int MAXN = 100 + 10; const double ESP = 10e-8; const double Pi = atan(1.0) * 4; const int INF = 0xffffff; const int MOD = 10000007; using namespace std; char edge[MAXN]; int vet[MAXN]; int dp1[MAXN/2][MAXN/2],dp2[MAXN/2][MAXN/2]; int fin[MAXN]; int N; int main(){ // freopen("input.txt","r",stdin); int ans = -INF; scanf("%d",&N); for(int i = 0;i < N;i++){ getchar(); scanf("%c %d",&edge[i],&vet[i]); } for(int t = 0;t < N;t++){ //从t位置为起点 for(int i = 0;i < N;i++){ //进行矩阵的初始化 dp1[i][i] = vet[(t+i)%N]; dp2[i][i] = dp1[i][i]; } for(int l = 2;l <= N;l++){ //j-i的长度 for(int i = 0;i < N-l+1;i++){ int maxv = -INF; int minv = INF; int j = i+l-1; for(int k = i;k < j;k++){ if(edge[(k+1+t)%N] == ‘t‘){ //这里也要相应的改变 maxv = max(maxv,dp1[i][k] + dp1[(k+1)%N][j]); minv = min(minv,dp2[i][k] + dp2[(k+1)%N][j]); } else{ maxv = max(maxv,dp1[i][k] * dp1[(k+1)%N][j]); maxv = max(maxv,dp2[i][k] * dp2[(k+1)%N][j]); //负负得正 minv = min(minv,dp1[i][k] * dp2[(k+1)%N][j]); //正负相乘 minv = min(minv,dp2[i][k] * dp2[(k+1)%N][j]); minv = min(minv,dp2[i][k] * dp1[(k+1)%N][j]); //正负相乘 } } dp1[i][j] = maxv; //进行赋值 dp2[i][j] = minv; } } ans = max(ans,dp1[0][N-1]); fin[t] = dp1[0][N-1]; } printf("%d\n",ans); for(int i = 0;i < N;i++){ if(fin[i] == ans){ printf("%d ",i+1); } } printf("\n"); return 0; }
d(i,j)为 i - j 的最优费用,则 d(i,j) - min{ d(i,k) + d(k,j) + a[j] - a[i] };
先小区间求值……
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <cstdlib> const int MAXN = 1000 + 10; const double ESP = 10e-8; const double Pi = atan(1.0) * 4; const int INF = 0xffffff; const int MOD = 10000007; using namespace std; int a[MAXN]; int dp[MAXN][MAXN]; int main(){ // freopen("input.txt","r",stdin); int len; while(~scanf("%d",&len) && len){ int n; scanf("%d",&n); for(int i = 1;i <= n;i++){ scanf("%d",&a[i]); } memset(dp,0,sizeof(dp)); a[0] = 0; a[n+1] = len; for(int l = 2;l <= n+1;l++){ for(int i = 0;i+l <= n+1;i++){ int j = i+l; dp[i][j] = INF; for(int k = i+1;k < j;k++){ int tmp = dp[i][k] + dp[k][j] + a[j]-a[i]; if(tmp < dp[i][j]){ dp[i][j] = tmp; } } } } printf("The minimum cutting is %d.\n",dp[0][n+1]); } return 0; }
时间: 2024-10-26 07:14:59