• poj1179 Polygon **


      1 /*
    2 * 枚举第一次断开的边,然后DP,
    3 *
    4 * DP还是很简单的, 类似矩阵连乘
    5 * 需要注意的是:由于负负得正,所以你不能只算最大值.
    6 * 也就是说要计算多边形上连续的一段所能达到的最小值和最大值.
    7 *
    8 * 难的是断开第k条边后如何给剩下的边重新编号
    9 *
    10 * 这里建立了一个映射,如断开第k条边,
    11 * 则原来的第k+1条边编号为0,原来的第k-1条边编号为n-2.
    12 *
    13 * getNum(i, k)函数用于计算断开第k条边后新编号为i的边的原编号
    14 *
    15 *
    16 *
    17 */
    18 #include <cstdio>
    19 using namespace std;
    20
    21 const int maxn = 50 + 4;
    22 const int inf = 10000000;
    23 int n, vertex[maxn];
    24 char edge[maxn];
    25 int dpmin[maxn][maxn], dpmax[maxn][maxn], initdp[maxn];
    26
    27 inline int cal(int edgeNum, int a, int b){
    28 if(edge[edgeNum] == 't')
    29 return a + b;
    30 else
    31 return a * b;
    32 }
    33 inline int getNum(int i, int k){
    34 if(i > n-k-2)
    35 return i-(n-k-1);
    36 else
    37 return i+k+1;
    38 }
    39
    40 //断开第k条边
    41 //
    42 void init(int k){
    43 for(int i=0; i<n; i++)
    44 for(int j=0; j<n; j++){
    45 dpmin[i][j] = inf;
    46 dpmax[i][j] = -inf;
    47 }
    48 int j;
    49 for(int i=0; i<n; i++){
    50 j = getNum(i, k);
    51 //初始化
    52 dpmax[i][i] = dpmin[i][i] = initdp[j];
    53 //为了后边DP时计算方便,把顶点的信息记录在dp数组里
    54 dpmax[(i+1)%n][i] = dpmin[(i+1)%n][i] = vertex[j];
    55 }
    56
    57 }
    58
    59 inline int min(int a, int b, int c, int d, int e){
    60 int ans = a;
    61 if(ans > b) ans = b;
    62 if(ans > c) ans = c;
    63 if(ans > d) ans = d;
    64 if(ans > e) ans = e;
    65 return ans;
    66 }
    67 inline int max(int a, int b, int c, int d, int e){
    68 int ans = a;
    69 if(ans < b) ans = b;
    70 if(ans < c) ans = c;
    71 if(ans < d) ans = d;
    72 if(ans < e) ans = e;
    73 return ans;
    74 }
    75
    76
    77 int main(){
    78 scanf("%d\n", &n);
    79
    80 char tmp;
    81 int ii;
    82 for(int i=0; i<n; i++){
    83 scanf("%c %d", &edge[i], &vertex[i]);
    84 if(i<n-1) scanf("%c", &tmp);
    85 }
    86
    87 for(int i=0; i<n; i++){
    88 ii = (i-1+n) % n;
    89 initdp[i] = cal(i, vertex[ii], vertex[i]);
    90 }
    91
    92 int jj, ans=-inf, rec[maxn], top = 0;
    93 for(int k=0; k<n; k++){
    94 init(k);
    95 for(int l=1; l<n-1; l++){
    96 for(int i=0; i<n-1-l; i++){
    97 for(int j=i; j<=i+l; j++){
    98 jj = getNum(j, k);
    99 ii = (j-1+n)%n;
    100 dpmin[i][i+l]=min(dpmin[i][i+l],
    101 cal(jj, dpmin[i][ii], dpmin[j+1][i+l]),
    102 cal(jj, dpmax[i][ii], dpmin[j+1][i+l]),
    103 cal(jj, dpmin[i][ii], dpmax[j+1][i+l]),
    104 cal(jj, dpmax[i][ii], dpmax[j+1][i+l]));
    105 dpmax[i][i+l]=max(dpmax[i][i+l],
    106 cal(jj, dpmin[i][ii], dpmin[j+1][i+l]),
    107 cal(jj, dpmax[i][ii], dpmin[j+1][i+l]),
    108 cal(jj, dpmin[i][ii], dpmax[j+1][i+l]),
    109 cal(jj, dpmax[i][ii], dpmax[j+1][i+l]));
    110 }
    111 }
    112 }
    113 //记录答案
    114 if(ans < dpmax[0][n-2]){
    115 ans = dpmax[0][n-2];
    116 top = 0;
    117 rec[top++] = k;
    118 }
    119 else if(ans == dpmax[0][n-2])
    120 rec[top++] = k;
    121
    122 }
    123
    124 //answer
    125 printf("%d\n", ans);
    126 for(int i=0; i<top-1; i++)
    127 printf("%d ", rec[i]+1);
    128 printf("%d\n", rec[top-1]+1);
    129
    130
    131 return 0;
    132 }
  • 相关阅读:
    SQL Server 查看新建、重建、重组索引进度
    CentOS PostgreSQL 12 主从复制(主从切换)
    CentOS PostgreSQL 12 安装
    SQL Server 当前事务无法提交,而且无法支持写入日志文件的操作。
    MySQL 碎片整理
    MySQL 5.7 MHA(mha4mysql-manager依赖包)
    MySQL- 5.7 sys schema
    MySQL InnoDB 恢复(recovery)详细流程
    MySQL学习(二十五)order by 逻辑
    jvm学习(一)DirectByteBuffer堆外内存浅析
  • 原文地址:https://www.cnblogs.com/longdouhzt/p/2417013.html
Copyright © 2020-2023  润新知