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 }
  • 相关阅读:
    GridView跨列
    html的积累
    什么是json?
    关于string
    Effective C# Item38:定制和支持数据绑定
    Effective C# Item44:为应用程序创建特定的异常类
    Effective C# Item42:利用特性简化反射
    Effective C# Item47:选择安全代码
    Effective C# Item43 : 避免过度使用反射
    Effective C# Item39 : 使用.NET验证
  • 原文地址:https://www.cnblogs.com/njczy2010/p/5515788.html
Copyright © 2011-2022 走看看