• 九度OJ 1260:珍珠项链 (字符串处理、DP)


    时间限制:1 秒

    内存限制:32 兆

    特殊判题:

    提交:101

    解决:27

    题目描述:

    假设有一条珍珠项链,有很多珍珠,r代表红色, b代表蓝色, w代表白色。
    假设你在某一处剪开之后,你会沿着顺时针和逆时针方向收集珠子,但是收集珠子有一个条件:
    1.只能收集同一种颜色的珠子 2.w可以表示红色也可以表示蓝色。
    你怎么剪才能收集到尽可能多的珠子。
    例如下图中,在2、3之间剪开,逆时针方向可以收集到3颗珠子(r),顺时针方向能收集到3颗珠子(b),这样2、3之间剪开能收集6颗
            12
            rr
        10 w  w 3
         9 b  b 4
         8 w  w 5
            rr
            76

    输入:

    输入包含一个仅有'r','w','b'三个字符的字符串。

    输出:

    可能有多组测试数据,对于每组数据,
    输出最多可以收集多少颗珍珠。

    样例输入:
    rrwbwrrwbw
    样例输出:
    6

    思路:

    此题相较于一般的DP,麻烦之处是字符串构成一个圆。因此不是从1到n的DP,而是从第1个n到第n个n的递归。

    代码比较晦涩,只因我一时手贱非要写成两个方向统一的函数代码。


    代码:

    #include <stdio.h>
    #include <string.h>
     
    #define N 100000
     
    void count(int c[N][2], int a[N], int n, int begin, int towards)
    {
        int i = begin;
        while (i != begin + n*towards && a[(i+n)%n] == 2)
            i += towards;
        //printf("begin=%d, i=%d, towards=%d
    ", begin, i, towards);
        c[begin][0] = c[begin][1] = (i - begin)*towards;
        if (i != begin + n*towards)
        {
            int color = a[(i+n)%n];
            i += towards;
            while (i != begin + n*towards && a[(i+n)%n] != 1-color)
                i += towards;
            c[begin][color] = (i - begin)*towards;
        }
    }
     
    void dp(int c[N][2], int a[N], int n, int i, int j)
    {
        int color = a[i];
        if (color == 2)
        {
            c[i][0] = (c[j][0] < n) ? (c[j][0] + 1) : n;
            c[i][1] = (c[j][1] < n) ? (c[j][1] + 1) : n;
        }
        else
        {
            c[i][color] = c[j][color] + 1;
            c[i][1-color] = 0;
        }
    }
     
    int Max(int x, int y)
    {
        return (x > y) ? x : y;
    }
     
    int main(void)
    {
        int n, i, j, k;
        char s[N+1];
        int a[N];
        int c[2][N][2];
     
        while (scanf("%s", s) != EOF)
        {
            n = strlen(s);
            for (i=0; i<n; i++)
            {
                if (s[i] == 'r')
                    a[i] = 0;
                else if (s[i] == 'b')
                    a[i] = 1;
                else
                    a[i] = 2;
                //printf("%d", a[i]);
            }
            //printf("
    ");
     
            for (k=0; k<2; k++)
            {
                int towards = k*2 - 1;
                count(c[k], a, n, 0, towards);
                //printf("c[%d][%d]=%d,%d
    ", k, 0, c[k][0][0], c[k][0][1]);
                for (i=-towards; i!=-(n*towards); i-=towards)
                {
                    j = (i+towards+n)%n;
                    int ii = (i+n)%n;
                    dp(c[k], a, n, ii, j);
                    //printf("c[%d][%d]=%d,%d
    ", k, ii, c[k][ii][0], c[k][ii][1]);
                }
            }
     
            int max = 0;
            for (i=0; i<n; i++)
            {
                int t1 = Max(c[0][i][0], c[0][i][1]);
                j = (i+1)%n;
                int t2 = Max(c[1][j][0], c[1][j][1]);
                max = (t1+t2 > max) ? t1+t2 : max;
                if (max >= n)
                {
                    max = n;
                    break;
                }
            } 
            printf("%d
    ", max);
        }   
             
        return 0;
    }   
    /**************************************************************
        Problem: 1260
        User: liangrx06
        Language: C
        Result: Accepted
        Time:210 ms
        Memory:2896 kb
    ****************************************************************/


    编程算法爱好者。
  • 相关阅读:
    pthread线程内存布局
    用户空间实现线程 内核实现线程 线程的调度
    堆 虚拟内存
    Operating System-Thread(3)用户空间和内核空间实现线程
    Linux进程地址空间与虚拟内存
    虚拟地址
    物理内存,虚拟内存,进程地址空间
    CPU中MMU的作用
    进程地址空间与虚拟存储空间的理解
    虚拟地址空间
  • 原文地址:https://www.cnblogs.com/liangrx06/p/5083808.html
Copyright © 2020-2023  润新知