POJ 1179 Polygon(DP)

本题一次水过,由此纪念一下。(实际上,我这个年纪做这种题实在很丢人)。

题目链接。大意:给一个多边形,每个顶点有一个值,每个边编号从1到N,边的属性是加或者乘。首先先拆掉一条边,剩下的如下做:选定一条边以及这条边的两个端点(两个数)用新顶点替换(新顶点即:按照这条边的属性(加或乘)算出这两个数的乘积或者和)。到最后剩一个点,也就是一个值。求这些值的最大值输出,并输出此时最先拆掉的是哪条边。

用2个一维数组存放这个多边形,其一存放点,其二存放边(加或者乘)。将这2个数组当作循环队列一样的使用即可穷举去掉的边。需要另外2个数组记录最大值和最小值(因为两个负数相乘为正,所以要记录最小值)。

设maxDp[i][j] (minDp[i][j])为从i到j的多边形的最终值的最大值(最小值),再从1到N枚举多边形长度(j-i),依次算出长度为1到N的子多边形的最终值。由此自底向上就算出此多边形的最终值的最大值。我的代码如下:

   1: #include <iostream>
   2: #include <algorithm>
   3:  
   4: using namespace std;
   5: const int VERTEX_SIZE = 50;
   6: const long MAX_INT = (1<<15);
   7: const long MIN_INT = -(1<<15);
   8:  
   9: int vertex[VERTEX_SIZE];
  10: char label[VERTEX_SIZE];
  11: long maxDp[VERTEX_SIZE][VERTEX_SIZE];
  12: long minDp[VERTEX_SIZE][VERTEX_SIZE];
  13:  
  14: void init(const int size, const int front)
  15: {
  16:     for (int i=0; i<VERTEX_SIZE; i++)
  17:     {
  18:         for (int j=0; j<VERTEX_SIZE; j++)
  19:         {
  20:             if (j==i)
  21:                 minDp[i][j] = maxDp[i][j] = vertex[i];
  22:             else
  23:             {
  24:                 maxDp[i][j] = MIN_INT;
  25:                 minDp[i][j] = MAX_INT;
  26:             }
  27:         }
  28:     }
  29: }
  30:  
  31: int getRes(const int size, const int front)
  32: {
  33:     int end=(front+size)%size;
  34:     for (int len=1; len<size; len++)
  35:     {
  36:         bool flag=true;
  37:         for (int i=front; flag || (i+len)%size!=end; i=(i+1)%size)
  38:         {
  39:             flag = false;
  40:             int j=(i+len)%size;
  41:             for (int k=i; k!=j; k=(k+1)%size)
  42:             {
  43:                 if (label[(k+1)%size]=='x')
  44:                 {
  45:                     maxDp[i][j] = max(maxDp[i][j], maxDp[i][k]*maxDp[(k+1)%size][j]);
  46:                     maxDp[i][j] = max(maxDp[i][j], minDp[i][k]*minDp[(k+1)%size][j]);
  47:  
  48:                     minDp[i][j] = min(minDp[i][j], maxDp[i][k]*maxDp[(k+1)%size][j]);
  49:                     minDp[i][j] = min(minDp[i][j], maxDp[i][k]*minDp[(k+1)%size][j]);
  50:                     minDp[i][j] = min(minDp[i][j], minDp[i][k]*maxDp[(k+1)%size][j]);
  51:                     minDp[i][j] = min(minDp[i][j], minDp[i][k]*minDp[(k+1)%size][j]);
  52:                 }
  53:                 else if (label[(k+1)%size]=='t')
  54:                 {
  55:                     maxDp[i][j] = max(maxDp[i][j], maxDp[i][k]+maxDp[(k+1)%size][j]);
  56:                     minDp[i][j] = min(minDp[i][j], minDp[i][k]+minDp[(k+1)%size][j]);
  57:                 } 
  58:             }
  59:         } 
  60:     }
  61:  
  62:     return maxDp[front][(front+size-1)%size];
  63: }
  64:  
  65: int main()
  66: {
  67:     int size=0;
  68:     cin >> size;
  69:     for (int i=0; i<size; i++)
  70:         cin >> label[i] >> vertex[i];
  71:     int recordLabel[VERTEX_SIZE]={0};
  72:     int maxNum = MIN_INT;
  73:     for (int i=0; i<size; i++)
  74:     {
  75:         init(size, i);
  76:         recordLabel[i] = getRes(size, i);
  77:         maxNum = max(maxNum, recordLabel[i]);
  78:     }
  79:     cout << maxNum << endl;
  80:     bool first = true;
  81:     for (int i=0; i<size; i++)
  82:     {
  83:         if (maxNum==recordLabel[i] && first)
  84:         {
  85:             cout << (i+1);
  86:             first = false;
  87:             continue;
  88:         }
  89:         if (maxNum==recordLabel[i] && (!first))
  90:         {
  91:             cout << ' ' << (i+1);
  92:             continue;
  93:         }
  94:     }
  95:     cout << endl;
  96:  
  97:     return 0;
  98: } 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值