小白题解 Codeforces 266A Stones on the Table

来源:互联网 发布:js怎么设置display 编辑:程序博客网 时间:2024/06/05 00:24

(LIS问题经典变形)题目链接:点击打开链接

题目大意:给定一排只有三种颜色的n个石头,要求移除掉尽可能少的石头使两两相邻的石头颜色都不同。

分析:这道题目可以从移除以后的结果进行分析,不难想象,最优解一定是原来排列的“最长不同子序列”。则可以用LIS模板进行编码。另外由于n只有50,则用最朴素的O(n*n)算法即可。好啦,下面是AC代码(另附上该种算法的LIS模板一份)。

#include<cstdio>int main(){    int n;    char colar[55];    int cnt[55];    for(int i=0;i<55;i++)        cnt[i]=0;    scanf("%d",&n);    scanf("%s",colar);
/*这里还有个小插曲,一开始用的%c逐个读取字符,但出bug了,原因是输入n之后的空格留在缓冲区,
  被%c读取,导致colar[0]始终为换行符。。。           以后要注意这个问题啊!*/
    int maxn=0;    for(int i=0;i<n;i++)    {        cnt[i]=1;        for(int j=0;j<=i-1;j++)        {            if(colar[j]!=colar[i]&&cnt[i]<cnt[j]+1)            {                cnt[i]=cnt[j]+1;            }        }        if(cnt[i]>maxn)            maxn=cnt[i];    }    printf("%d\n",n-maxn);    return 0;}

下面是O(n*n)复杂度的LIS模板

#include <cstdio>#define SIZE 1001int main(){    int i, j, n, maxl;    int a[SIZE];    int d[SIZE];   //d[i]表示以a[i]结尾的最长子序列长度    while(scanf("%d",&n)==1)    {        for (i = 0; i < n; i++)        {            scanf("%d",&a[i]);            d[i]=1;        }        maxl = 0;        for (i = 0; i < n; i++)        {            for (j = 0; j <= i - 1; j++)            {                if (a[j] < a[i] && d[i] < d[j] + 1)                    //要注意 d[i] < d[j] + 1它是为了在连续几个 d[i]相同时 只加一次                     d[i] = d[j] + 1;            }            if (d[i] > maxl) maxl = d[i];        }        printf("%d\n",maxl);    }    return 0;}