zoukankan      html  css  js  c++  java
  • HDU 5691 Sitting in Line 状压dp

    Sitting in Line

    题目连接:

    http://acm.hdu.edu.cn/showproblem.php?pid=5691

    Description

    度度熊是他同时代中最伟大的数学家,一切数字都要听命于他。现在,又到了度度熊和他的数字仆人们玩排排坐游戏的时候了。游戏的规则十分简单,参与游戏的N个整数将会做成一排,他们将通过不断交换自己的位置,最终达到所有相邻两数乘积的和最大的目的,参与游戏的数字有整数也有负数。度度熊为了在他的数字仆人面前展现他的权威,他规定某些数字只能在坐固定的位置上,没有被度度熊限制的数字则可以自由地交换位置。

    Input

    第一行一个整数T,表示T组数据。
    每组测试数据将以如下格式从标准输入读入:

    N

    a1p1

    a2p2

    :

    aNPN

    第一行,整数 N(1≤N≤16),代表参与游戏的整数的个数。

    从第二行到第 (N+1) 行,每行两个整数,ai(−10000≤ai≤10000)、pi(pi=−1 或 0≤pi<N),以空格分割。ai代表参与游戏的数字的值,pi代表度度熊为该数字指定的位置,如果pi=−1,代表该数字的位置不被限制。度度熊保证不会为两个数字指定相同的位置。

    Output

    第一行输出:"Case #i:"。i代表第i组测试数据。

    第二行输出数字重新排列后最大的所有相邻两数乘积的和,即max{a1⋅a2+a2⋅a3+......+aN−1⋅aN}。

    Sample Input

    2
    6
    -1 0
    2 1
    -3 2
    4 3
    -5 4
    6 5
    5
    40 -1
    50 -1
    30 -1
    20 -1
    10 -1

    Sample Output

    Case #1:
    -70
    Case #2:
    4600

    Hint

    题意

    题解:

    状压dp

    dp[i][j]表示状态为i的时候,最后一个是j的最大值

    然后直接转移就好了,现在他是第几个,就是前面有多少个1就好了

    这个可以预处理出来

    代码

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <conio.h>
    
    using namespace std;
    
    const int maxn = 16;
    const int inf = 2e9;
    
    int dp[1 << 16][17];
    
    int p[maxn] , N , a[maxn] , counter[1 << 16];
    
    inline void Update( int & x , int v ){
        x = max( x , v );
    }
    
    int main(){
        int Case , cas = 0;
        scanf("%d",&Case);
        for(int i = 0 ; i < ( 1 << 16) ; ++ i) counter[i] = __builtin_popcount(i);
        while(Case--){
            scanf("%d",&N);
            for(int j = 0 ; j < ( 1 << N ) ; ++ j ) for(int k = 0 ; k <= N ; ++ k) dp[j][k] = -inf;
            for(int i = 0 ; i < N ; ++ i){
                scanf("%d%d" , a + i , p + i );
            }
            a[N] = 0;
            dp[0][N]=0;
            for(int i = 0 ; i < ( 1 << N) ; ++ i)
                for(int j = 0 ; j <= N ; ++ j)
                    if( dp[i][j] != - inf )
                        for(int v = 0 ; v < N ; ++ v)
                            if(  ( (i >> v & 1) == 0) && ( p[v] == -1 || p[v] == counter[i] ) )
                                Update( dp[i | ( 1 << v )][ v ] , dp[i][j] + a[j] * a[v] );
            int ans = -inf;
            for(int i = 0 ; i <= N ; ++ i ) Update( ans , dp[ (1<<N)-1 ][i] );
            printf("Case #%d:
    " , ++ cas);
            printf("%d
    " , ans);
        }
        return 0;
    }
  • 相关阅读:
    sina sae搭建wordpress数据库配置
    Daper返回DataTable
    第4章 jQuery中的事件和动画
    第3章 ,jQuery中的DOM操作
    第2章 jQuery选择器
    第1章 认识jQuery
    MyBatis基本查询、条件查询、查询排序
    《Head First Servlets & JSP》-13-过滤器和包装器
    《Head First Servlets & JSP》-12-Web应用安全
    《Head First Servlets & JSP》-11-Web应用部署
  • 原文地址:https://www.cnblogs.com/qscqesze/p/5516139.html
Copyright © 2011-2022 走看看