poj 1179 Polygon(动态规划:矩阵连乘加强)

初看这个题很复杂的样子,但其实还是比较好做的

因为涉及到环,所以我们在输入得到的串后面再补一个串即可

每次求长度为n的dp值即可

因为这里涉及到负数,所以要考虑到负负相乘得正的情况

因此在计算的过程中既要保存最大值,又要保存最小值

算法类似于矩阵连乘dp[i][j] = {dp[i][k]  "+\*" dp[k+1][j]}

期间写错了好多个字符,导致wa了一次抓狂

0ms代码如下:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#define MAXN 150
#define LL long long
#define INF 0x7fffffff
using namespace std;

LL a[MAXN], dp[MAXN][MAXN][2];
char ch[MAXN];

LL Operate_max(int x, int y, int z) {//计算x z之间以y断开的最大值
    if(ch[y+1] == 't')
        return dp[x][y][0]+dp[y+1][z][0];
    else if(ch[y+1] == 'x')
        return max(dp[x][y][1]*dp[y+1][z][1], dp[x][y][0]*dp[y+1][z][0]);
}

LL Operate_min(int x, int y, int z) {//计算x z之间以y断开的最小值
    if(ch[y+1] == 't')
        return dp[x][y][1]+dp[y+1][z][1];
    else if(ch[y+1] == 'x')
        return min(dp[x][y][1]*dp[y+1][z][1], dp[x][y][0]*dp[y+1][z][0]);
}

int main(void) {
    int n, tmpn;
    LL tmp1, tmp2;
    while(scanf("%d", &n) != EOF) {
        memset(dp, 0, sizeof(dp));//初始化
        for(int i=1; i<=n; ++i) {
            cin >> ch[i] >> a[i] ;//读入字符串用cin处理
            ch[n+i] = ch[i];
            a[n+i] = a[i];
            dp[i][i][0] = dp[i][i][1] = a[i];
            dp[n+i][n+i][0] = dp[n+i][n+i][1] = a[n+i];
        }

        //dp[i][j] = dp[i][k], ch[k+1], dp[k+1][j];
        tmpn = n<<1;
        for(int r=1; r<n; ++r) {
            for(int i=1; i<=tmpn; ++i) {
                int j = i+r;

                if(j > tmpn)
                    break;

                tmp1 = Operate_max(i, i, j);
                tmp2 = Operate_min(i, i, j);

                dp[i][j][0] = max(tmp1, tmp2);
                dp[i][j][1] = min(tmp1, tmp2);

                for(int k=i+1; k<j; ++k) {

                    tmp1 = Operate_max(i, k, j);
                    tmp2 = Operate_min(i, k, j);
                    dp[i][j][0] = max(dp[i][j][0], max(tmp1, tmp2));
                    dp[i][j][1] = min(dp[i][j][1], min(tmp1, tmp2));

                }
                //printf("%d - %d\t %lld\t%lld\n", i, j, dp[i][j][0], dp[i][j][1]);
            }
        }
        LL ans = max(dp[1][n][0], dp[1][n][1]);
        for(int i=2; i<=n; ++i) {
            ans = max(ans, dp[i][i+n-1][0]);
            //ans = max(ans, dp[i][i+n-1][1]);
        }

        cout << ans << endl;
        for(int i=1; i<=n; ++i) {
            if(ans == dp[i][i+n-1][0]) {
            //从i处开始长度为n的dp最大值等于最后的结果,则一定从i-1处先断开,因为下标从1开始,所以输出i
                printf("%d ", i);
            }
        }
        puts("");
    }
    return 0;
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值