2019 TCO Round 1B——[ 状压DP ]

第一题是 EllysSki 。

题意:给n个数,求两个方向的最长递减区间。

可以O(n)。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
int Mx(int a,int b){return a>b?a:b;}

class EllysSki{
public:
  int getMax(vector <int> height);
};

int EllysSki::getMax(vector <int> height)
{
  int n=height.size(),ans=0;
  for(int i=0;i<n;i++)
    {
      int j=i;
      while(j+1<n&&height[j+1]<=height[j])
    j++;
      ans=Mx(ans,j-i+1); i=j;
    }
  for(int i=n-1;i>=0;i--)
    {
      int j=i;
      while(j&&height[j-1]<=height[j])
    j--;
      ans=Mx(ans,i-j+1); i=j;
    }
  return ans;
}
View Code

第二题是 EllysTeleport 。

题意:连边,找最长链。

自己写了tarjan,没调出来。其实 n2 暴力也行。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
int Mx(int a,int b){return a>b?a:b;}
int Mn(int a,int b){return a<b?a:b;}
const int N=1e4+5;
int n,h[N],to[N]; bool vis[N];
class EllysTeleport{
  int fnd(int x)
  {
    int l=1,r=n,ret=0;
    while(l<=r)
      {
    int mid=l+r>>1;
    if(h[mid]<=x)ret=mid,l=mid+1;
    else r=mid-1;
      }
    return ret;
  }
public:
  int getMax(int N, int H1, int A, int B, int P, int Q, int M)
  {
    n=N; h[1]=H1;
    for(int i=2;i<=n;i++)
      h[i]=((ll)h[i-1]*A+B)%M;
    sort(h+1,h+n+1);
    for(int i=1;i<=n;i++)
      {
    int d=((ll)h[i]*P+Q)%M;
    to[i]=fnd(d);
      }
    int ans=0;
    for(int i=1;i<=n;i++)
      {
    memset(vis,0,sizeof vis);
    int cnt=1,cr=to[i]; vis[i]=1;
    while(cr&&!vis[cr])
      {
        cnt++;vis[cr]=1;cr=to[cr];
      }
    ans=Mx(ans,cnt);
      }
    return ans;
  }
};
View Code

第三题是 EllysPearls 。

题意:n(<=50) 个球排成一排,每个球是 m(<=15) 种颜色之一。一次操作可以拿出序列中任意一个球,再插进序列的任意一个位置。求最少操作次数使得相同颜色的球是一个区间。

题解:https://www.topcoder.com/blog/2019-topcoder-open-algorithm-round-1b-editorials/

颜色只有 15 ,考虑状压。 1 表示该颜色之前已经确定了一个位置,即当前球必须取出、融入之前自己颜色的区间。

特殊情况就是当前球不动,就能合法;所以再记目前最后的颜色是什么(可以是空)。

还可能遇到当前球,但是把它放在后面,即尚不确定当前颜色。发现这种情况和“融入之前自己颜色的区间”都是要花费1的代价,并且不改变状压的状态。

所以 dp[ i ][ j ][ s ] 表示前 i 个、末尾颜色是 j 、已经确定位置的颜色集合是 s ,即可转移。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int N=55,K=20,M=(1<<15)+5;
int n,m,a[N],bin[K],dp[2][K][M];
class EllysPearls{
  void cz(int &x,int y){if(y<x)x=y;}
public:
  int getMin(int tN, int tM, vector <int> pearls)
  {
    n=tN; m=tM; for(int i=0;i<n;i++)a[i+1]=pearls[i];
    bin[0]=1;for(int i=1;i<=m;i++)bin[i]=bin[i-1]<<1;
    memset(dp[1],0x3f,sizeof dp[1]);
    dp[1][0][0]=0; bool u=1,v=0;
    for(int i=1;i<=n;i++,swap(u,v))
      {
    memset(dp[v],0x3f,sizeof dp[v]);
    for(int j=0;j<=m;j++)
      for(int s=0;s<bin[m];s++)//[m]not[n]
        {
          int tp=dp[u][j][s]; if(tp>N)continue;
          int d=bin[a[i]-1];
          cz(dp[v][j][s],tp+1);
          if(!j||j==a[i])
        cz(dp[v][a[i]][s|d],tp);
          if(!(s&d))
        cz(dp[v][a[i]][s|d],tp);
        }
      }
    int ans=N;
    for(int j=0;j<=m;j++)
      for(int s=0;s<bin[m];s++)
    cz(ans,dp[u][j][s]);
    return ans;
  }
};
View Code

 

posted on 2019-05-02 00:52  Narh  阅读(179)  评论(0编辑  收藏  举报

导航