Multiplication Puzzle (poj 1651)

来源:互联网 发布:用java输出梯形 编辑:程序博客网 时间:2024/06/07 19:23

题目大意

给出一个整数序列,从中依次删除元素,如果删除元素card[i],就把card[i]card[i1]card[i+1]加到删除的代价里。求最小的删除代价。不允许删除最左和最右的元素。在删除结束后,序列只剩下两个元素。

分析

动态规划。第一眼就可以看出和矩阵乘法很像。
自顶向上考虑问题。考虑最后一次删除,设最后一次删除的元素是card[k],那么删除的代价是card[0]card[n1]card[k]+S[0][k]+S[k][n1],其中S[0][k]表示删除序列card[0,1,...,k]需要的代价,S[k][n1]表示删除序列card[k,k+1,...,n1]所需要的代价。
注意每次序列删除最终都会留下头和尾,所以是S[0][k]而不是S[0][k1].
边界条件:需要让S[i][i+1]=0

代码

#include <iostream>#include <vector>#include <algorithm>#include <map>#include <string>#include <string.h>#include <queue>#include <set>#include <limits.h>using namespace std;// multiplication puzzle// 找一个符合条件的顺序,暴力方法是O(n!)// 动态规划// S[i,j] = min(S[i,k] + S[k,j] + A[i]A[k]A[j]) if j-i > 2, k >i && k <j// S[i,j] = A[i]*A[i+1]*A[j] if j-i=2const int MAXN = 105;int cards[MAXN];int S[MAXN][MAXN];  //动态规划数组,S[i][j]表示以i开头以j结尾的链的最小乘积void dp(int n) {    for (int r = 3; r <= n; r++) {        // r是链长        for (int i = 0; i < n - r + 1; i++) {            // i是链头            int j = i + r - 1; //j是链尾            cout << i << " " << j << endl;            // 接下来求S[i][j]            int min_k = -1;            for (int k = i+1; k < j; k++) {                // k是要选择剔出的数的下标                int left = S[i][k]; // S[i][i]初始化为0,其余初始化为最大值                int right = S[k][j];                int tmp_res = left + right + cards[i] * cards[k] * cards[j];                cout << left << " " << right << " " << tmp_res << endl;                if (tmp_res < S[i][j]) {                    S[i][j] = tmp_res;                    min_k = k;                }            }            cout << "k: " << cards[min_k] << endl;        }    }}int main() {    int n;     cin >> n;    for (int i = 0; i < n; i++) {        cin >> cards[i];    }    for (int i = 0; i < n; i++) {        for (int j = 0; j < n; j++) {            S[i][j] = INT_MAX;        }    }    for (int i = 0; i < n; i++) {        S[i][i] = 0;    }    for (int i = 0; i < n - 1; i++) {        S[i][i + 1] = 0;    }    dp(n);    cout << S[0][n - 1] << endl;    return 0;}

反思

因为一开始就觉得是矩阵乘法,所以直接开始写矩阵乘法的代码。但是因为没有考虑清楚整个问题,所以在边界上出错。实际还是对问题分析得不透彻。以后要认真分析问题,就题论题。

原创粉丝点击