SPOJ 364 Pocket Money 简单DP

跟矩阵链乘同类型的题……

输出用%llu不是%I64u……

几组数据:

14
1+2*4+3*4+5*0
0*5*6+7*3+2
3+0+6+7+0+4
4*5+7*1*1+1
2*0+3*4*0+5*6+7+8
1+2+3*1+2*1+0
0+2*2+3*0+4
8*9*0+2
2*0+1+0*3
2*0*3+7+1*0*3
1+3*0*5+2
1+1+1+1+1
2*1+1+2*1+2*1+6
1*2*4*0*6*3

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cctype>
#include <algorithm>

#define LL unsigned long long int

using namespace std;

const int MAXN = 110;

int cntNum, cntOp;
char str[MAXN];
char op[MAXN];
LL num[MAXN];
bool vis[MAXN][MAXN];
LL dpMax[MAXN][MAXN];
LL dpMin[MAXN][MAXN];

void show()
{
    printf("All nums: \n");
    for ( int i = 0; i < cntNum; ++i )
        printf( "%I64d ", num[i] );

    printf("\nAll Ops:\n");
    for ( int i = 0; i < cntOp; ++i )
        putchar( op[i] );
    puts("");
    return;
}

void chuli()
{
    cntNum = cntOp = 0;
    int len = strlen(str);
    for ( int i = 0; i < len; ++i )
    {
        LL tmp = 0;
        while ( i < len && isdigit( str[i] ) )
        {
            tmp = tmp * 10 + ( str[i] - '0' );
            ++i;
        }
        num[ cntNum++ ] = tmp;
        if ( i < len )
            op[ cntOp++ ] = str[i];
    }

    //show();
    return;
}

LL DPMAX( int l, int r )
{
    LL &res = dpMax[l][r];
    if ( vis[l][r] ) return res;

    vis[l][r] = true;
    if ( l == r ) return res = num[l];
    res = 0;

    for ( int k = l; k < r; ++k )
    {
        if ( op[k] == '+' )
            res = max( res, DPMAX( l, k ) + DPMAX( k + 1, r ) );
        else if ( op[k] == '*' )
            res = max( res, DPMAX( l, k ) * DPMAX( k + 1, r ) );
    }
    //printf( "dp[%d][%d]=%I64u\n", l, r, res );

    return res;
}

LL DPMIN( int l, int r )
{
    LL &res = dpMin[l][r];
    if ( vis[l][r] ) return res;

    vis[l][r] = true;
    if ( l == r ) return res = num[l];
    bool first = true;

    for ( int k = l; k < r; ++k )
    {
        if ( op[k] == '+' )
        {
            if ( first )
            {
                res = DPMIN( l, k ) + DPMIN( k + 1, r );
                first = false;
            }
            else
                res = min( res, DPMIN( l, k ) + DPMIN( k + 1, r ) );
        }
        else if ( op[k] == '*' )
        {
            if ( first )
            {
                res = DPMIN( l, k ) * DPMIN( k + 1, r );
                first = false;
            }
            else
                res = min( res, DPMIN( l, k ) * DPMIN( k + 1, r ) );
        }
    }
    //printf( "dp[%d][%d]=%I64u\n", l, r, res );
    return res;
}

int main()
{
    int T;
    scanf( "%d", &T );
    while ( T-- )
    {
        scanf( "%s", str );
        chuli();
        memset( dpMax, 0, sizeof(dpMax) );
        memset( dpMin, 0, sizeof(dpMin) );

        memset( vis, false, sizeof(vis) );
        LL maxx = DPMAX( 0, cntNum - 1 );

        memset( vis, false, sizeof(vis) );
        LL minn = DPMIN( 0, cntNum - 1 );

        printf( "%llu %llu\n", maxx, minn );
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/GBRgbr/p/3248274.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值