Buy Low, Buy Lower

来源:互联网 发布:mac安装win8.1教程 编辑:程序博客网 时间:2024/04/29 15:35

题意:有一个大小为N的数列,数列中都是以正整数代表的价格,求最长的降序子列的长度以及个数(子列中元素的先后顺序要与原来的数列中相同,而且对于全部元素都相等的子列只能算作一个)

解题思路

  1. 用price[0...N-1]来代表这个数列,用f[i] = j来代表以price[i]为第一个元素的最长降序子列的长度为j
  2. 初始条件f[N - 1] = 1,倒序滚雪球的过程:f[i] = max{f[j] + 1},其中j = [i + 1, N - 1]而且price[i] > price[j]。如果没有满足条件的j,则f[i] = 1
  3. 用c[i] = j来代表以price[i]为第一个元素的最长降序子列的长度为j
  4. 初始条件为c[N - 1] = 1,倒序滚雪球的过程:c[i] = sum{c[j]},其中j = [i + 1, N - 1],f[i] = f[j] + 1而且price[i] > price[j]。在DP过程中要注意对重复的判断,也就是如果f[j]相同并且对应的price[j]也想同,就代表出现重复,只能算一次
  5. 遍历f[i],找到最大的f[i]即为最长降序子列的长度。然后将这些等于最大长度的f[i]对应的c[i]加起来,在这个过程中同样要注意判断重复,方法与4中相同
  6. 最后得到的c[i]之和就是最后的结果,在处理过程中发现这个和比较大,用内置的数据类型无法表示,于是用一个长度为100的数组来保存c[i]的每一位数,相加的过程自行写一个类似竖式加法的函数就行

代码

/*ID: zc.rene1LANG: CPROG: buylow */#include<stdio.h>#include<stdlib.h>#include<string.h>int N;int price[5000];int f[5000];int c[5000][100];int visited[5000];int result[5000];void GetF(void){    int i, j;    int max;    memset(f, 0, 5000 * sizeof(int));    f[N - 1] = 1;    for (i=N-2; i>=0; i--)    {max = 1;for (j=i+1; j<N; j++){    if (price[i] > price[j])    {if (f[j] + 1 > max){    max = f[j] + 1;}    }}f[i] = max;    }}int IsVisited(int dest, int len){    int i;    for (i=0; i<len; i++)    {if (visited[i] == dest){    return 1;}    }    return 0;}void Add(int a[100], int b[100]){    int i = 0, remain = 0, sum;    while (i < 100)    {sum = a[i] + b[i] + remain;if (sum >= 10){    remain = 1;}else{    remain = 0;}a[i] = (sum) % 10;i++;    }}void GetC(void){    int i, j, index;        memset(c, 0, 5000 * 100 * sizeof(int));    c[N-1][0] = 1;    for (i=N-2; i>=0; i--)    {memset(visited, 0, N * sizeof(int));index = 0;for (j=i+1; j<N; j++){    if ((f[i] == f[j] + 1) && (price[i] > price[j]))    {if (IsVisited(price[j], index)){    continue;}else{    visited[index++] = price[j];    Add(c[i], c[j]);}    }}if (index == 0){    c[i][0] = 1;}    }}int main(void){    FILE *fin, *fout;    int i, index, max_f;    int max_c[100];    fin = fopen("buylow.in", "r");    fout = fopen("buylow.out", "w");    fscanf(fin, "%d", &N);    for (i=0; i<N; i++)    {fscanf(fin, "%d", &price[i]);    }    GetF();    GetC();    max_f = -1;    for (i=0; i<N; i++)    {if (f[i] > max_f){    max_f = f[i];}    }    memset(max_c, 0, 100 * sizeof(int));    memset(visited, 0, N * sizeof(int));    index = 0;    for (i=0; i<N; i++)    {if (f[i] == max_f){    if (IsVisited(price[i], index))    {continue;    }    else    {visited[index++] = price[i];Add(max_c, c[i]);    }}    }    fprintf(fout, "%d ", max_f);    i = 99;    while (max_c[i] == 0)    {i--;    }    while (i >= 0)    { fprintf(fout, "%d", max_c[i]);i--;    }    fprintf(fout, "\n");    return 0;}


原创粉丝点击