百度之星-资格赛Problem B

Problem B
Accepts: 1408 Submissions: 5317
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Problem Description
度熊面前有一个全是由1构成的字符串,被称为全1序列。你可以合并任意相邻的两个1,从而形成一个新的序列。对于给定的一个全1序列,请计算根据以上方法,可以构成多少种不同的序列。
Input
这里包括多组测试数据,每组测试数据包含一个正整数N,代表全1序列的长度。
1\leq N \leq 2001≤N≤200
Output
对于每组测试数据,输出一个整数,代表由题目中所给定的全1序列所能形成的新序列的数量。
Sample Input
1
3
5
Sample Output
1
3
8
Hint
如果序列是:(111)。可以构造出如下三个新序列:(111), (21), (12)。
分析:
和资格赛的第二题一样,直接用递推即可。再考虑第n个(最后一个)1时,(1):他不合并,剩下的n-1个可以按规定合并,所以a[n]=a[n-1];(2):他与第n-1个1合并,剩下的n-2个可以按规定合并。所以a[n]=a[n-1]+a[n-2];
需要注意的是:题目N<200,所以要考虑到高进度加法问题。以下有两种高精度加法(由于200还是很小的所以第一种也可以)。第二种是实现一个大整数类,可以达到第10000位,使他支持高精度加法,有点难度,建议读者慢慢研究体会。
方法一:

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int maxn = 1005;
int a[maxn][maxn];

void init(int a[maxn][maxn])
{
    memset(a,0,sizeof(a));
    a[1][0] = 1;
    a[2][0] = 2;
    for(int i = 3; i <= 1002; i++)
    {
        for(int j = 0; j < maxn ; j++) { a[i][j] += a[i-1][j] + a[i-2][j]; if(a[i][j] >= 10)
            {
                a[i][j] -= 10;
                a[i][j+1]++;
            }
        }
    }
}

int main()
{
    int n,i;
    init(a);
    while(scanf("%d", &amp;n) != EOF)
    {
        for(i = 1000; i >= 0; i--)
            if(a[n][i]) break;
        for(; i >= 0; i--)
            printf("%d",a[n][i]);
        printf("\n");
    }
    return 0;
}

方法二:

#include <iostream>
#include <string.h>
#include <cstdio>
using namespace std;

const int MAXN = 100000000;
const int N = 500;
const int M = 10000;

struct bign {
    int len;
    int s[N];

    bign() {
    this -> len = 1;
    memset(s, 0, sizeof(s));
    }
    bign (int number) {*this = number;}
    bign (const char* number) {*this = number;}

    bign change(bign cur) {
    bign now;
    now = cur;
    for (int i = 0; i < cur.len; i++) now.s[i] = cur.s[cur.len - i - 1]; return now; } void delZore() { // 删除前导0. 
    bign now = change(*this); while (now.s[now.len - 1] == 0 && now.len > 1) {
        now.len--;
    }
    *this = change(now);
    }

    void put() {    // 输出数值。
    delZore();
    printf("%d", s[0]);
    for (int i = 1; i < len; i++)
        printf("%08d", s[i]);
    }

    bign operator = (const char *number) {
    memset(s, 0, sizeof(s));
    int dist = strlen(number);
    int k = dist % 8;
    for (int i = 0; i < k; i++)
        s[0] = s[0] * 10 + number[i] - '0';
    int cnt = 0;
    for (int i = k; i < dist; i++, cnt++)
        s[cnt / 8 + 1] = s[cnt / 8 + 1] * 10 + number[i] - '0';
    len = cnt / 8 + 1;
    return *this;
    }

    bign operator = (int number) {
    char string[N];
    sprintf(string, "%d", number);
    *this = string;
    return *this;
    }

    bign operator + (const bign &cur){
    bign sum, a, b;
    sum.len = 0;
    a = a.change(*this);
    b = b.change(cur);

    for (int i = 0, g = 0; g || i < a.len || i < b.len; i++){
        int x = g;
        if (i < a.len) x += a.s[i];
        if (i < b.len) x += b.s[i];
        sum.s[sum.len++] = x % MAXN;
        g = x / MAXN;
    }
    return sum.change(sum);
    }
};

bign num[M + 10];
int main() {
    int n;
    num[1]=1;
    num[2]=2;
    num[3]=3;
    num[4]=5;
    for (int i = 5; i < M + 5; i++)
    num[i] = num[i - 1] + num[i - 2];
    while (scanf("%d", &n) == 1) {
    num[n].put();
    printf("\n");
    }
    return 0;
}
The 0-1 Knapsack Problem is a classic optimization problem in computer science and mathematics. The problem is as follows: Given a set of items, each with a weight and a value, determine the items to include in a collection so that the total weight is less than or equal to a given limit and the total value is as large as possible. The 0-1 indicates that each item can only be included once or not at all. This problem can be solved using dynamic programming. We can create a two-dimensional array where the rows represent the items and the columns represent the weight limit. For each item and weight limit, we can calculate the maximum value that can be obtained by either including the item or excluding it. We can then fill in the array row by row until we reach the final row, which represents the optimal solution. Here is an example implementation of the 0-1 Knapsack Problem in Java: ``` public class Knapsack { public static int knapsack(int[] values, int[] weights, int limit) { int[][] dp = new int[values.length + 1][limit + 1]; for (int i = 1; i <= values.length; i++) { for (int j = 1; j <= limit; j++) { if (weights[i-1] > j) { dp[i][j] = dp[i-1][j]; } else { dp[i][j] = Math.max(dp[i-1][j], dp[i-1][j-weights[i-1]] + values[i-1]); } } } return dp[values.length][limit]; } public static void main(String[] args) { int[] values = {60, 100, 120}; int[] weights = {10, 20, 30}; int limit = 50; int result = knapsack(values, weights, limit); System.out.println("Maximum value: " + result); } } ``` In this example, we have three items with values of 60, 100, and 120 and weights of 10, 20, and 30, respectively. We want to find the maximum value we can obtain with a weight limit of 50. The result is 220, which indicates that we should select items 2 and 3 to maximize the value while staying under the weight limit.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值