2018焦作网络赛Mathematical Curse

本文介绍了一种使用动态规划算法解决特定数学问题的方法,该问题是在给定的数字序列中插入运算符以获得最大可能结果。文章详细解释了状态转移方程,并提供了完整的C++代码实现。

题意:开始有个数k,有个数组和几个运算符。遍历数组的过程中花费一个运算符和数组当前元素运算。运算符必须按顺序花费,并且最后要花费完。问得到最大结果。

用maxv[x][y]记录到第x个元素,用完了第y个运算符时的最大值,minv[x][y]为最小。那么maxv[x][y]要么第y个运算符在x-1之前就用过了,即max[x-1][y],要么x-1之前用到了y-1,再在x的位置用运算符y;因此就是两者取大。还有如果当前遇到的是负数,那么要用最小的来乘,实际上是3者取大。

//#pragma comment(linker,"/STACK:1024000000,1024000000") 
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
#include <stack>
#include <list>
using namespace std;
typedef long long lon;
lon maxv[1010][7],minv[1010][7],arr[1010];
const lon SZ=1000010,INF=0x7FFFFFFFFFFFFFFF;

lon ope(lon a,lon b,char opr)
{
    if(opr=='+')return a+b;
    else if(opr=='-')return a-b;
    else if(opr=='*')return a*b;
    else return a/b;
}

int main()
{
    std::ios::sync_with_stdio(0);
    //freopen("d:\\1.txt","r",stdin); 
    lon casenum;
    cin>>casenum;
    for(lon time=1;time<=casenum;++time)
    {
        lon n,m,k;
        cin>>n>>m>>k;
        for(lon i=1;i<=n;++i)cin>>arr[i];
        string str;
        cin>>str;
        str=" "+str;
        for(lon i=1;i<=n;++i)
        {
            for(lon j=1;j<=m;++j)
            {
                maxv[i][j]=-INF;
                minv[i][j]=INF;
            }
         } 
        maxv[1][1]=minv[1][1]=ope(k,arr[1],str[1]);
        for(lon i=1;i<=n;++i)maxv[i][0]=minv[i][0]=k;
        for(lon i=2;i<=n;++i)
        {
            for(lon j=1;j<=m;++j)
            {
                if(j>i)break;
                else
                {
                    maxv[i][j]=max(maxv[i-1][j],ope(maxv[i-1][j-1],arr[i],str[j]));
                    maxv[i][j]=max(maxv[i][j],ope(minv[i-1][j-1],arr[i],str[j]));
                    //if(i==2&&j==1)cout<<"m: "<<minv[i-1][j-1]<<" "<<arr[i]<<endl;
                    minv[i][j]=min(minv[i-1][j],ope(maxv[i-1][j-1],arr[i],str[j]));
                    minv[i][j]=min(minv[i][j],ope(minv[i-1][j-1],arr[i],str[j]));
                }
            }
        }
//        for(lon i=1;i<=n;++i)
//        {
//            for(lon j=1;j<=m;++j)
//            {
//                cout<<maxv[i][j]<<" ";
//            }cout<<endl;
//        }
        lon resmax=-INF,resmin=INF;
        for(lon i=1;i<=n;++i)resmax=max(resmax,maxv[i][m]);
        //for(lon i=1;i<=n;++i)resmin=max(resmin,maxv[i][m]);
        cout<<resmax<<endl;
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/gaudar/p/9688155.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值