zoukankan      html  css  js  c++  java
  • hdu 5691 Sitting in Line

    传送门

    Sitting in Line

    Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
    Total Submission(s): 293    Accepted Submission(s): 143


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

    N

    a1p1

    a2p2



    aNPN

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

    从第二行到第 (N+1) 行,每行两个整数,ai(10000ai10000)pi(pi=1 或 0pi<N),以空格分割。ai代表参与游戏的数字的值,pi代表度度熊为该数字指定的位置,如果pi=1,代表该数字的位置不被限制。度度熊保证不会为两个数字指定相同的位置。
     
    Output
    第一行输出:"Case #i:"。i代表第i组测试数据。

    第二行输出数字重新排列后最大的所有相邻两数乘积的和,即max{a1a2+a2a3+......+aN1aN}
     
    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
     
    Source
     
    Recommend
    wange2014   |   We have carefully selected several similar problems for you:  5695 5694 5693 5692 5690 
     
     
     
    题意:
    数组中有些元素位置被固定了,有些可以换位置,求
    max{a1a2+a2a3+......+aN1aN}
     
    题解:
    真不容易,田神给我说了思路,还编了好久2333

    状压dp,比赛时没时间思考了。。。

    其实,观察所要求的max{a1a2+a2a3+......+aN1aN}

    可以发现,你发完前 i - 1 位 元素后,准备放第 i 位 元素时,当前的 max 只 与 a[i-1] 有关了 (a[i - 1] * a[i]),所以可以用状压dp

    定义 dp[o][i] 为放完第i位(以a[i] 为结尾),状态 o 时的max

    遍历的顺序见代码

    17232841 2016-05-21 22:22:30 Accepted 5691 1294MS 11724K 2946B G++ czy
      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstdlib>
      4 #include <cstring>
      5 #include <algorithm>
      6 #include <vector>
      7 
      8 using namespace std;
      9 
     10 #define N 19
     11 #define ll long long
     12 
     13 ll ma;
     14 ll a[N];
     15 int p[N];
     16 int have[N];
     17 int n;
     18 ll dp[ (1 << 17) ][N];
     19 int tot;
     20 ll inf;
     21 vector<int> G[N];
     22 
     23 int cal(int x)
     24 {
     25     int ret = 0;
     26     while(x){
     27         ret += (x & 1);
     28         x /= 2;
     29     }
     30     return ret;
     31 }
     32 
     33 void ini()
     34 {
     35     int o;
     36     for(o = 0;o < n;o++){
     37         G[o].clear();
     38     }
     39     for(o = 0;o < tot;o++){
     40         G[ cal(o) ].push_back(o);
     41     }
     42 }
     43 
     44 int main()
     45 {
     46 
     47     int T;
     48     //freopen("in.txt","r",stdin);
     49     //freopen("out.txt","w",stdout);
     50     scanf("%d",&T);
     51     for(int ccnt = 1;ccnt <= T;ccnt++){
     52         scanf("%d",&n);
     53         inf = (1LL << 60);
     54         ma = -inf;
     55         tot = (1 << n);
     56         ini();
     57         int i;
     58         memset(have,-1,sizeof(have));
     59         for(i = 0;i < n;i++){
     60             scanf("%I64d%d",&a[i],&p[i]);
     61             if(p[i] != -1){
     62                 have[ p[i] ] = i;
     63             }
     64         }
     65         int o,nt;
     66         for(o = 0;o < tot;o++){
     67             for(i = 0;i < n;i++){
     68                 dp[o][i] = -inf;
     69             }
     70         }
     71         for(i = 0;i < n;i++){
     72             if(p[i] == 0 || p[i] == -1){    //放在第一个
     73                 dp[ (1 << i) ][i] = 0;
     74             }
     75         }
     76 
     77         /*
     78         for(i = 0;i < n;i++){
     79             for(int j = 0;j < G[i].size();j++){
     80                 printf(" i =%d j = %d g= %d
    ",i,j,G[i][j]);
     81             }
     82         }*/
     83         for(i = 1;i < n;i++){      //放第i位
     84             int sz = G[i].size();
     85             for(int j = 0;j < sz;j++){  //遍历含有i个1的所有数
     86                 o = G[i][j];
     87                 for(int k = 0;k < n;k++)    //把第k个数放在第i位
     88                 {
     89 
     90                     if( o & (1 << k) ) continue;    //k已经放了
     91                     if( p[k] != -1 && p[k] != i ) continue; //k被固定了
     92                     if( have[i] != -1 && have[i] != k ) continue;   //位置i被固定了
     93                     nt = o | (1 << k);
     94                     //printf(" i = %d o = %d k = %d nt = %d
    ",i,o,k,nt);
     95                     for(int pr = 0;pr < n;pr++){
     96                         if( (o & (1 << pr ) ) == 0) continue;    //pr不在o里
     97                         if( dp[o][pr] == -inf ) continue;
     98                         //printf(" i = %d o = %d k = %d nt = %d pr = %d
    ",i,o,k,nt,pr);
     99                         dp[nt][k] = max(dp[nt][k],dp[o][pr] + a[pr] * a[k]);
    100                     }
    101                 }
    102             }
    103         }
    104         /*
    105         for(o = 0;o < tot;o++){
    106             for(i = 0;i < n;i++){
    107                 printf(" o = %d i = %d dp = %I64d
    ",o,i,dp[o][i]);
    108             }
    109         }*/
    110         for(i = 0;i < n;i++){
    111             ma = max(ma,dp[tot - 1][i]);
    112         }
    113         printf("Case #%d:
    ",ccnt);
    114         printf("%I64d
    ",ma);
    115     }
    116 
    117     return 0;
    118 }
  • 相关阅读:
    Construct Binary Tree from Preorder and Inorder Traversal
    Construct Binary Tree from Inorder and Postorder Traversal
    Maximum Depth of Binary Tree
    Sharepoint 2013 创建TimeJob 自动发送邮件
    IE8 不能够在Sharepoint平台上在线打开Office文档解决方案
    TFS安装与管理
    局域网通过IP查看对方计算机名,通过计算机名查看对方IP以及查看在线所有电脑IP
    JS 隐藏Sharepoint中List Item View页面的某一个字段
    SharePoint Calculated Column Formulas & Functions
    JS 两个一组数组转二维数组
  • 原文地址:https://www.cnblogs.com/njczy2010/p/5515788.html
Copyright © 2011-2022 走看看