zoukankan      html  css  js  c++  java
  • POJ 1179

    题目链接:http://poj.org/problem?id=1179

    Time Limit: 1000MS Memory Limit: 10000K

    Description

    Polygon is a game for one player that starts on a polygon with N vertices, like the one in Figure 1, where N=4. Each vertex is labelled with an integer and each edge is labelled with either the symbol + (addition) or the symbol * (product). The edges are numbered from 1 to N. 

    On the first move, one of the edges is removed. Subsequent moves involve the following steps: 
    pick an edge E and the two vertices V1 and V2 that are linked by E; and 
    replace them by a new vertex, labelled with the result of performing the operation indicated in E on the labels of V1 and V2. 
    The game ends when there are no more edges, and its score is the label of the single vertex remaining. 

    Consider the polygon of Figure 1. The player started by removing edge 3. After that, the player picked edge 1, then edge 4, and, finally, edge 2. The score is 0. 

    Write a program that, given a polygon, computes the highest possible score and lists all the edges that, if removed on the first move, can lead to a game with that score. 

    Input

    Your program is to read from standard input. The input describes a polygon with N vertices. It contains two lines. On the first line is the number N. The second line contains the labels of edges 1, ..., N, interleaved with the vertices' labels (first that of the vertex between edges 1 and 2, then that of the vertex between edges 2 and 3, and so on, until that of the vertex between edges N and 1), all separated by one space. An edge label is either the letter t (representing +) or the letter x (representing *). 

    3 <= N <= 50 
    For any sequence of moves, vertex labels are in the range [-32768,32767]. 

    Output

    Your program is to write to standard output. On the first line your program must write the highest score one can get for the input polygon. On the second line it must write the list of all edges that, if removed on the first move, can lead to a game with that score. Edges must be written in increasing order, separated by one space.

    Sample Input

    4
    t -7 t 4 x 2 x 5

    Sample Output

    33
    1 2

    题意:

    给出一个由无向边和节点组成的环,每个节点上有一个数字,每条边上有一个运算符(加或乘),

    现在先割断一条边,然后环就成为一个链,然后你每次可以将这条链上的一条边缩成一个点,产生的新点的权值就是两个节点配合边运算所产生的结果。

    不停地缩边成点,直到最后只有一个点为止,求这个点的权值最大是多少。

    并给出所有能产生这个最大值的首先割断的边的编号,要求从小到大输出。

    题解:

    区间DP,周赛上wyb出的毒瘤题,每次两个小区间合并的时候,要记得有可能两个最小的负数相乘可能会产生正数最大值。

    因此需要同时维护区间最小值和最大值。

    AC代码:

    #include<cstdio>
    #include<vector>
    #include<algorithm>
    using namespace std;
    typedef pair<int,int> pii;
    const int INF=0x3f3f3f3f;
    const int maxn=55;
    
    int n;
    int op[2*maxn],nm[2*maxn];
    pii dp[2*maxn][2*maxn];
    inline int calc(int type,int a,int b){return type?a*b:a+b;}
    inline void updatemn(int &x,int y){if(x>y) x=y;}
    int solve(int l,int r)
    {
        for(int s=2;s<=r-l+1;s++)
        {
            for(int st=l,ed=st+s-1;ed<=r;st++,ed++)
            {
                dp[st][ed].first=-INF;
                dp[st][ed].second=INF;
                for(int mid=st+1;mid<=ed;mid++)
                {
                    pii le=dp[st][mid-1];
                    pii ri=dp[mid][ed];
    
                    int tmp1=calc(op[mid],le.first,ri.first);
                    dp[st][ed].first=max(dp[st][ed].first,tmp1);
                    dp[st][ed].second=min(dp[st][ed].second,tmp1);
    
                    int tmp2=calc(op[mid],le.first,ri.second);
                    dp[st][ed].first=max(dp[st][ed].first,tmp2);
                    dp[st][ed].second=min(dp[st][ed].second,tmp2);
    
                    int tmp3=calc(op[mid],le.second,ri.first);
                    dp[st][ed].first=max(dp[st][ed].first,tmp3);
                    dp[st][ed].second=min(dp[st][ed].second,tmp3);
    
                    int tmp4=calc(op[mid],le.second,ri.second);
                    dp[st][ed].first=max(dp[st][ed].first,tmp4);
                    dp[st][ed].second=min(dp[st][ed].second,tmp4);
                }
            }
        }
        return dp[l][r].first;
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=0;i<n;i++)
        {
            int m; char o[2];
            scanf("%s",o); op[i]=op[n+i]=(o[0]=='x');
            scanf("%d",&m); nm[i]=nm[n+i]=m;
        }
    
        for(int i=0;i<2*n;i++) dp[i][i]=make_pair(nm[i%n],nm[i%n]);
        int ans=-INF;
        for(int c=0;c<n;c++) ans=max(ans,solve(c,c+n-1));
    
        vector<int> E;
        for(int c=0;c<n;c++) if(dp[c][c+n-1].first==ans) E.push_back(c+1);
        sort(E.begin(),E.end());
        printf("%d
    ",ans);
        for(int i=0;i<E.size();i++) printf("%d%c",E[i],(i==E.size()-1)?'
    ':' ');
    }

    数据:

    5
    x 2 x 3 t 1 t 7 x 4
    
    224
    4
    
    
    5
    x -3 t -1 t -7 t -4 x -2
    
    30
    1 5
    
    
    3
    t 0 x 1 t -2
    
    0
    1
    
    
    30
    x 1 t 1 x 1 t 1 t 1 x 1 x 1 x 1 x 1 x 1 x 1 t 1 t 1 x 1 t 1 x 1 x 1 t 1 x 1 x 1 t 1 x 1 x 1 x 1 x 1 x 1 t 1 x 1 x 1 x 1
    
    288
    1 3 6 7 8 9 10 11 14 16 17 19 20 22 23 24 25 26 28 29 30
    
    
    48
    x 1 x 2 x 1 x -1 t 1 x -1 x -1 x 1 t 1 t -1 x 1 t 2 x 1 x 2 t 1 x 1 x -1 x -2 x 1 x 1 t 1 x 1 t 1 x 1 x 1 x 1 t 1 x 1 x 1 x 1 x 1 x 1 x 1 x -1 t 1 x 1 x -1 x -1 t 1 x 1 t 1 x 1 x 1 x -1 t 1 t -1 t -1 x 1
    
    23328
    45
  • 相关阅读:
    单例模式
    grails2.3.11第二课
    grails2.3.11第一课
    【安全】requests和BeautifulSoup小试牛刀
    【解决】国内访问github过慢
    基于Ubuntu14.10的Hadoop+HBase环境搭建
    基于adt-bundle的Android开发环境搭建
    【解决】SAE部署Django1.6+MySQL
    【解决】Django项目废弃SQLite3拥抱MySQL
    【OpenGL】画立方体
  • 原文地址:https://www.cnblogs.com/dilthey/p/9826890.html
Copyright © 2011-2022 走看看