poj1179-polygon(动态规划)

动归这个算法还是很明显的,首先先对输入的所有操作数和操作符进行保存,第一步,删掉一条边,这个循环遍历,然后接下来的n-1条边每条边和其两个顶点进行删除根据边进行运算将值传递到代替他们的新顶点上,知道所有的边被删除完,剩下的值就是最大值。

#include <cstdio>
#include <cstring>
#include <iostream>

using namespace std;
const int maxlen=51;
const int maxnum=999999999;
const int minnum=-999999999;
int operand[maxlen]; //操作数
char operat[maxlen]; //操作符

int resmax[maxlen][maxlen]; //i到j合并的最大值
int resmin[maxlen][maxlen]; //i到j合并的最小值
int ansmax; //临时最大值
bool dedge[maxlen]; //最大结果时所删边
int n,i,j,k,steplen,deledge;
int tempmax,tempmin;

void init() //初始化
{
     for(i=0;i<n;++i)
          for(j=0;j<n;++j)
     {
          if(i==j) resmax[i][j]=resmin[i][j]=operand[i];
          else
          {
               resmax[i][j]=minnum;
               resmin[i][j]=maxnum;
          }
     }
}
int main()
{
     scanf("%d",&n);
     for(i=0;i<n;++i)
          cin>>operat[i]>>operand[i];
     ansmax=minnum;
     for(deledge=0;deledge<n;++deledge)  //删除一条边
     {
          init();        //初始化
          for(steplen=2;steplen<=n;++steplen)          //一条边最短的长度是两个顶点,最长的是n个顶点
          {
               for(i=deledge;i<=n+deledge-steplen;i++)           //从删掉的那条边的一个顶点开始,如果i大于n,再从原来开始
               {
                    j=i+steplen-1;           //steplen长度限制
                    for(k=i;k<j;++k)
                    {
                         int kleftmax=resmax[i%n][k%n];     //mod解决i大小限制
                         int kleftmin=resmin[i%n][k%n];
                         int krightmax=resmax[(k+1)%n][j%n];
                         int krightmin=resmin[(k+1)%n][j%n];
                         if(operat[(k+1)%n]=='t')
                         {
                              tempmax=kleftmax+krightmax;
                              tempmin=kleftmin+krightmin;
                         }
                         else
                         {
                              tempmax=max(max(kleftmax*krightmax,kleftmin*krightmin),max(kleftmin*krightmax,kleftmax*krightmin));
                              tempmin=min(min(kleftmax*krightmax,kleftmin*krightmin),min(kleftmin*krightmax,kleftmax*krightmin));
                         }
                         resmax[i%n][j%n]=max(resmax[i%n][j%n],tempmax);
                         resmin[i%n][j%n]=min(resmin[i%n][j%n],tempmin);
                    }
               }
          }
          if(resmax[deledge][(deledge+n-1)%n]>ansmax)            //记录最大值和最大值时所删边
          {
               memset(dedge,0,sizeof(dedge));
               ansmax=resmax[deledge][(deledge-1+n)%n];
               dedge[deledge]=1;
          }
          else if(resmax[deledge][(deledge-1+n)%n]==ansmax)
               dedge[deledge]=1;
     }
     cout<<ansmax<<endl;
     for(i=0;i<n;++i)
          if(dedge[i]) cout<<i+1<<" ";
	return 0;
}



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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值