最优矩阵链乘

主要大区间化为小区间……

先小区间求值……

状态转移方程 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;
}
View Code

 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;
}

 uva 10003 http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=847&problem=944&mosmsg=Submission+received+with+ID+15274403

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;
}

 

posted @ 2015-04-05 20:13  寒饼干  阅读(335)  评论(0编辑  收藏  举报