• Codeforces 453B Little Pony and Harmony Chest:状压dp【记录转移路径】


    题目链接:http://codeforces.com/problemset/problem/453/B

    题意:

      给你一个长度为n的数列a,让你构造一个长度为n的数列b。

      在保证b中任意两数gcd都为1的情况下,使得 ∑|a[i]-b[i]|最小。

      让你输出构造的数列b。

      (1<=n<=100, 1<=a[i]<=30)

    题解:

      因为1<=a[i]<=30,所以有1<=b[i]<=60,此时才有可能最优。

      因为b中任意两数gcd为1,所以对于一个质因子p[i]只会在一个b[i]中用到。

      所以先处理出1到60这些数所要用到的质因子,状压存在数组f[i]中,第i位为1表示要用到质因子p[i]。

      另外,这题中59这个质因子是用不到的。

      因为它能构成的60以内的数只有59,然而对于最大的a[i]=30来说,b[i]选59和选1是等效的。

      这样就只剩16个质因子了。否则用17个会被卡时间和空间。

     

      然后开始状压dp。

      表示状态:

        dp[i][state] = min value

        表示该构造b[i]了,质因子的状态为state,此时原式的最小值。

      如何转移:

        dp[i+1][state|(1<<j)] = min dp[i][state] + |a[i]-j|

        枚举当前b[i]选了j,然后转移。

      边界条件:

        dp[0][0] = 0

        ohters = INF

        改构造b[0]了,此时一个质因子还没用过,原式初始为0。

      找出答案:

        枚举质因子状态state,显然最小的dp[n][state]为答案。

      然而现在只是知道了原式能达到的最小值,并不知道构造出的b数列。

      所以在转移的时候要记录下转移路径。

      新开两个数组:

        sel[i][state]:表示从上一步转移到这一步时,b[i-1]选了哪个数字

        sta[i][state]:若状态(i,state)是由(i-1,pre)转移而来的,则sta[i][state]为pre的值。

      所以每次转移的时候将路径和所选的数记录下来:

        if(dp[i][state]+d < dp[i+1][nex])

        {

          dp[i+1][nex]=dp[i][state]+d;

          sel[i+1][nex]=j;

          sta[i+1][nex]=state;

        }

      然后从最终答案的那一步,一直往前一个状态跳,就能找出构造的b数列了。

    AC Code:

      1 #include <iostream>
      2 #include <stdio.h>
      3 #include <string.h>
      4 #include <stack>
      5 #define MAX_N 105
      6 #define MAX_P 20
      7 #define MAX_D 65
      8 #define MAX_S ((1<<16)+50)
      9 #define INF 1000000000
     10 
     11 using namespace std;
     12 
     13 const int p[]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53};
     14 
     15 int n;
     16 int a[MAX_N];
     17 int dp[MAX_N][MAX_S];
     18 int sel[MAX_N][MAX_S];
     19 int sta[MAX_N][MAX_S];
     20 int f[MAX_D];
     21 
     22 inline int abs(int x)
     23 {
     24     return x>0 ? x : -x;
     25 }
     26 
     27 int get_f(int x)
     28 {
     29     int state=0;
     30     for(int i=0;i<16;i++)
     31     {
     32         while(x%p[i]==0)
     33         {
     34             x/=p[i];
     35             state|=(1<<i);
     36         }
     37     }
     38     return state;
     39 }
     40 
     41 void cal_f()
     42 {
     43     for(int i=1;i<=60;i++)
     44     {
     45         f[i]=get_f(i);
     46     }
     47 }
     48 
     49 void cal_dp()
     50 {
     51     memset(dp,0x3f,sizeof(dp));
     52     dp[0][0]=0;
     53     for(int i=0;i<n;i++)
     54     {
     55         for(int state=0;state<(1<<16);state++)
     56         {
     57             if(dp[i][state]<INF)
     58             {
     59                 for(int j=1;j<=60;j++)
     60                 {
     61                     if(!(state&f[j]))
     62                     {
     63                         int nex=(state|f[j]);
     64                         int d=abs(a[i]-j);
     65                         if(dp[i][state]+d<dp[i+1][nex])
     66                         {
     67                             dp[i+1][nex]=dp[i][state]+d;
     68                             sel[i+1][nex]=j;
     69                             sta[i+1][nex]=state;
     70                         }
     71                     }
     72                 }
     73             }
     74         }
     75     }
     76     int ans=INF;
     77     int now;
     78     for(int state=0;state<(1<<16);state++)
     79     {
     80         if(dp[n][state]<ans)
     81         {
     82             ans=dp[n][state];
     83             now=state;
     84         }
     85     }
     86     stack<int> stk;
     87     for(int i=n;i>=1;i--)
     88     {
     89         stk.push(sel[i][now]);
     90         now=sta[i][now];
     91     }
     92     while(!stk.empty())
     93     {
     94         cout<<stk.top()<<" ";
     95         stk.pop();
     96     }
     97     cout<<endl;
     98 }
     99 
    100 int main()
    101 {
    102     cin>>n;
    103     for(int i=0;i<n;i++) cin>>a[i];
    104     cal_f();
    105     cal_dp();
    106 }
  • 相关阅读:
    OpenState: Programming Platform-independent Stateful OpenFlow Applications Inside the Switch
    带状态论文粗读(二)
    In-band Network Function Telemetry
    基于微信小程序的失物招领系统的Postmortem
    OpenStack安装
    Alpha冲刺Day12
    冲刺合集
    Alpha冲刺Day11
    Alpha冲刺总结
    测试总结
  • 原文地址:https://www.cnblogs.com/Leohh/p/8267677.html
Copyright © 2020-2023  润新知