zoukankan      html  css  js  c++  java
  • HOJ 2156 &POJ 2978 Colored stones(线性动规)

    Colored stones
    Time Limit: 1000MS Memory Limit: 65536K
    Total Submissions: 1759 Accepted: 829
    Description

    You are given a row of m stones each of which has one of k different colors. What is the minimum number of stones you must remove so that no two stones of one color are separated by a stone of a different color?

    Input

    The input test file will contain multiple test cases. Each input test case begins with a single line containing the integers m and k where 1 ≤ m ≤ 100 and 1 ≤ k ≤ 5. The next line contains m integers x1, …, xm each of which takes on values from the set {1, …, k}, representing the k different stone colors. The end-of-file is marked by a test case with m = k = 0 and should not be processed.

    Output

    For each input case, the program should the minimum number of stones removed to satisfy the condition given in the problem.

    Sample Input

    10 3
    2 1 2 2 1 1 3 1 3 3
    0 0
    Sample Output

    2
    Hint

    In the above example, an optimal solution is achieved by removing the 2nd stone and the 7th stone, leaving three “2” stones, three “1” stones, and two “3” stones. Other solutions may be possible.

    Source

    这道题目,应该先去求给定的序列最长的子序列并满足,相同元素都是相邻的这个条件。于是我很容易想到了和LIS问题联系起来,就是开始去想。怎么也想不出来,看了题解,是要把状态表示成这样DP[i][j][k] 到序列第i个数的最长满足要求的子序列的状态j和子序列的最后一个元素是k。状态其实二进制压缩,表示k个元素是否在子序列中都出现过。我本来以为是简单的一维DP,到头来居然是三维的,有了这个状态,状态转移方程也好写了。我想在看过题解之后应该去思考,为什么这个状态是正确的,为什么要用这个状态表示,
    还有一点要注意,第二维的状态要是逆序的,因为代码中
    ss=s+(1<<(a[i]-1)); 如果正序会将已经求出ss又覆盖掉。

    #include <iostream>
    #include <string.h>
    #include <stdlib.h>
    #include <algorithm>
    #include <math.h>
    
    using namespace std;
    int n,k;
    int a[105];
    int dp[105][1<<5][6];
    int ans=0;
    int main()
    {
            while(scanf("%d%d",&n,&k)!=EOF)
            {
                            if(n==0&&k==0)
                                    break;
                    for(int i=1;i<=n;i++)
                            scanf("%d",&a[i]);
                    memset(dp,0,sizeof(dp));
                    for(int i=1;i<=n;i++)
                    {
                            for(int s=(1<<k)-1;s>=0;s--)
                            {
                                    for(int p=1;p<=k;p++)
                                    {
                                        dp[i][s][p]=dp[i-1][s][p];
                                    }
                                    if((1<<(a[i]-1))&s)
                                            dp[i][s][a[i]]=dp[i-1][s][a[i]]+1;
                                    else
                                    {
                                            int ss=s+(1<<(a[i]-1));
    
                                            for(int p=1;p<=k;p++)
                                            {
    
                                                    if(dp[i][ss][a[i]]<dp[i-1][s][p]+1)
                                                            dp[i][ss][a[i]]=dp[i-1][s][p]+1;
                                            }
                                    }
    
                            }
                    }
    
                    ans=0;
    
                    for(int s=0;s<=(1<<k)-1;s++)
                    {
                            for(int p=1;p<=k;p++)
                            {
                                    ans=max(ans,dp[n][s][p]);
                            }
    
                    }
                    printf("%d
    ",n-ans);
    
            }
            return 0;
    }
    
  • 相关阅读:
    Codeforces Round #694 (Div.1, Div.2)题解(2A-1D)(1E-1F待填)
    【Luogu日报#294】OI中你可能会用到的一些不等式及其证明 | 习题题解
    SP10570 LONGCS
    Unity 数字孪生笔记 工具介绍
    Unity3D 最佳数字孪生插件(一个基于Unity的自动化概念设计,仿真,虚拟调试和3D HMI的框架)
    Unity 数字孪生笔记 PiXYZ快速入门
    数据结构:堆排序
    HDU 4704 Sum (欧拉降幂+二项式公式+快速幂)
    Codeforces Goodbye2020部分题解
    Apache架构师的30条设计原则
  • 原文地址:https://www.cnblogs.com/dacc123/p/8228794.html
Copyright © 2011-2022 走看看