• 2016"百度之星"


    Sitting in Line

    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
     

    题解:

      我们设定dp[1<<16][16]:dp[i][j]:i为当前选取的状态并以第j个数结尾的最大值,那么答案就是 max{dp[全集][k]} k属于0到n

      对于dp[i][j] , i这个状态已经填了x个数,我们准备填第x+1个数时, 如果当前位置必填某个数,那么 就只更新以规定的这个数结尾转移方程

      如果没有那就 枚举那么可以任意放的数来更新相应的状态及答案

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include<queue>
    #include<vector>
    using namespace std;
    const int N = 1<<17, M = 1e6+10, mod = 1000000007,inf = 1e9;
    typedef long long ll;
    
    ll dp[1<<17][17];
    int n,a[N],p[N],H[N],F[N];
    int main() {
        int T,cas = 1;
        scanf("%d",&T);
        while(T--) {
            scanf("%d",&n);
            memset(H,0,sizeof(H));
            memset(F,-1,sizeof(F));
            int tmp = 0;
            for(int i=0;i<n;i++) {
                scanf("%d%d",&a[i],&p[i]);
                if(p[i]!=-1)
                 H[i] = 1,F[p[i]] = i;
            }
            for(int i=0;i<(1<<n);i++)
                for(int j=0;j<n;j++) dp[i][j] = -1e18;
      //      for(int i=0;i<n;i++)
        //        for(int j=0;j<n;j++) if(i!=j&&!H[i]&&!H[j]) dp[(1<<i)|(1<<j)][j] = a[i]*a[j], dp[(1<<i)|(1<<j)][i] = a[i]*a[j];
           if(F[0]!=-1) dp[(1<<F[0])][F[0]] = 0;
           else {
            for(int i=0;i<n;i++) {
                if(!H[i]) dp[(1<<i)][i] = 0;
            }
           }
           int U = (1<<n) - 1;
            for(int i=1;i<=U;i++) {
                int counts = 0;
                for(int j=0;j<n;j++) if((1<<j)&(i)) counts++;
                if(F[counts]!=-1) {
                    counts = F[counts];
                    for(int j=0;j<n;j++) if(i&(1<<j)&&counts!=j)dp[i|(1<<(counts))][counts] = max(dp[i][j]+a[j]*a[counts],dp[i|(1<<counts)][counts]);
                }
                else {
                    for(int k=0;k<n;k++) {
                        if((1<<k)&(i))
                        for(int j=0;j<n;j++) {
                           if(!((1<<j)&i)) {
                                dp[i|(1<<j)][j] = max(dp[i|(1<<j)][j],dp[i][k]+a[k]*a[j]);
                            }
                        }
                    }
                }
            }
            printf("Case #%d:
    ",cas++);
            ll ans = -1e18;
            for(int i=0;i<n;i++) ans = max(dp[U][i],ans) ;
            printf("%I64d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    我给老师发的邮件
    [LeetCode]Sum Root to Leaf Numbers
    [LeetCode]Binary Tree Inorder Traversal
    [LeetCode]Merge Sorted Array
    [LeetCode]Unique Paths II
    [LeetCode]Unique Paths
    [LeetCode]Sort Colors
    [LeetCode]Balanced Binary Tree
    [LeetCode]Valid Palindrome
    [LeetCode]Binary Tree Maximum Path Sum
  • 原文地址:https://www.cnblogs.com/zxhl/p/5515518.html
Copyright © 2020-2023  润新知