暑假做的题从后往前先更完

没怎么看懂

因为长期钻研算法, 无暇顾及个人问题,BUAA ACM/ICPC 训练小组的帅哥们大部分都是单身。某天,他们在机房商量一个绝妙的计划"一卡通大冒险"。这个计划是由wf最先提出来的,计划的内容是,把自己的联系方式写在校园一卡通的背面,然后故意将自己的卡"遗失"在某处(如水房,TD,食堂,主M。。。。)他们希望能有MM看到他们遗失卡,能主动跟他们联系,这样就有机会请MM吃饭了。他们决定将自己的一卡通夹在基本相同的书里,然后再将书遗失到校园的各个角落。正当大家为这个绝妙的计划叫好时,大家想到一个问题。很明显,如果只有一张一卡通,那么只有一种方法,即,将其夹入一本书中。当有两张一卡通时,就有了两种选择,即,将两张一卡通夹在一本书里,或者分开夹在不同的书里。当有三张一卡通时,他们就有了5种选择,即:
{{A},{B},{C}} , {{A,B},{C}}, {{B,C},{A}}, {{A,C},{B}} ,{{A,B,C}} 于是,
这个邪恶计划的组织者wf希望了解,如果ACM训练对里有n位帅哥(即有N张一卡通),那么要把这些一卡通夹到书里有多少种不同的方法。

包含多组数据,第一行为n,表示接下来有n组数据。以下每行一个数x,表示共有x张一卡通。(1≤x≤2000).

对每组数据,输出一行:不同的方法数,因为这个数可能非常大,我们只需要它除以1000的余数。

4
1
2
3
100
1
2
5
751

#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
using namespace std;
#define ll long long
int a[2005][2005];
int main()
{
    memset(a,0,sizeof(a));
    int i,j;
    a[0][1]=1;
    a[1][1]=1;
    a[1][2]=2;
    for(int i=2; i<=2002; i++)
    {
        a[i][1]=a[i-1][i-1];
        for(int j=2; j<=i+1; j++)
            a[i][j]=(a[i][j-1]+a[i-1][j-1])%1000;
    }
    int n;
    while(cin>>n)
    {
        while(n--)
        {
            int t;
            cin>>t;
            cout<<a[t+1][1]<<endl;
        }

    }

    return 0;
}

 

 

 

 

求连续的子序列中 和最大的:

当前这个数如果加上原来的,比他本身大,那他就是加上,作为尾,如果加上以前还不如他本身大,那他就要作为头继续开始。

Given a sequence a[1],a[2],a[3]......a[n], your job is to calculate the max sum of a sub-sequence. For example, given (6,-1,5,4,-7), the max sum in this sequence is 6 + (-1) + 5 + 4 = 14.

The first line of the input contains an integer T(1<=T<=20) which means the number of test cases. Then T lines follow, each line starts with a number N(1<=N<=100000), then N integers followed(all the integers are between -1000 and 1000).

For each test case, you should output two lines. The first line is "Case #:", # means the number of the test case. The second line contains three integers, the Max Sum in the sequence, the start position of the sub-sequence, the end position of the sub-sequence. If there are more than one result, output the first one. Output a blank line between two cases.

2
5 6 -1 5 4 -7
7 0 6 -1 1 -6 7 -5
Case 1:
14 1 4

Case 2:
7 1 6

#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int main()
{
    int t,n,a[100010],d[100010],sum,i,j,k,max0,k1;
    scanf("%d",&t);
    for(i=1;i<=t;i++)
    {
        scanf("%d",&n);
        memset(a,0,sizeof(a));
        memset(d,0,sizeof(d));
        max0=-100001;
        sum=0;
        for(j=1;j<=n;j++)
        {
            scanf("%d",&a[j]);
            d[j]=max(d[j-1]+a[j],a[j]);
            if(max0<d[j])
            {
                max0=d[j];
                k=j;
            }
        }
        for(j=k;j>=1;j--)
        {
            sum+=a[j];
            if(sum==max0)
                 k1=j;
        }
        printf("Case %d:\n",i);
        printf("%d %d %d\n",max0,k1,k);
        if(i!=t)
            putchar('\n');


    }
    return 0;
}

 

 

 

FatMouse believes that the fatter a mouse is, the faster it runs. To disprove this, you want to take the data on a collection of mice and put as large a subset of this data as possible into a sequence so that the weights are increasing, but the speeds are decreasing.

Input contains data for a bunch of mice, one mouse per line, terminated by end of file.

The data for a particular mouse will consist of a pair of integers: the first representing its size in grams and the second representing its speed in centimeters per second. Both integers are between 1 and 10000. The data in each test case will contain information for at most 1000 mice.

Two mice may have the same weight, the same speed, or even the same weight and speed.

Your program should output a sequence of lines of data; the first line should contain a number n; the remaining n lines should each contain a single positive integer (each one representing a mouse). If these n integers are m[1], m[2],..., m[n] then it must be the case that

W[m[1]] < W[m[2]] < ... < W[m[n]]

and

S[m[1]] > S[m[2]] > ... > S[m[n]]

In order for the answer to be correct, n should be as large as possible.
All inequalities are strict: weights must be strictly increasing, and speeds must be strictly decreasing. There may be many correct outputs for a given input, your program only needs to find one.

6008 1300
6000 2100
500 2000
1000 4000
1100 3000
6000 2000
8000 1400
6000 1200
2000 1900
4
4
5
9
7

#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<stack>
#include<vector>
#include<algorithm>
#include<iostream>
using namespace std;

int dp[1002]; // 以 i 结尾的最长上升子序列的长度
int ans[1002];// 结果数组
int pre[1002];// 标记 i 对应的上一个数据

struct MICE
{
    int w;
    int v;
    int pos; // 老鼠的编号
} mice[1001];

bool cmp(MICE a,MICE b)
{
    if(a.w==b.w)
        return a.v>b.v;
    return a.w<b.w;
}


int main()
{
    int n,m;
    int flag=1;
    int maxx=0;;
    memset(dp,0,sizeof(dp));
    memset(ans,0,sizeof(ans));
    memset(pre,0,sizeof(pre));
    while(scanf("%d %d",&mice[flag].w,&mice[flag].v)!=EOF)
    {

        mice[flag].pos=flag;
        flag++;
    }

    sort(mice,mice+flag,cmp);

    int len=0;

    for(int i=1; i<flag; i++) // 套dp 求LIS 的模板
    {
        dp[i]=1;
        pre[i]=i;
        for(int j=1; j<i; j++)
        {
            if(mice[i].w>mice[j].w&&mice[i].v<mice[j].v)
            {
                if(dp[i]<dp[j]+1){
                    dp[i]=dp[j]+1;
                    pre[i]=j; // 标记 i 的长度增加是从 j 增加得到的,记录下序号
                }
            }
        }
        if(len<dp[i])
        {
            len=dp[i]; // 求一个最长的 LIS 长度
            maxx=i;   // 记录 dp 增加的最后一个序号(不一定是老鼠的编号)
        }
    }
    cout<<len<<endl;

    int i=0;
    while(pre[maxx]!=maxx) //不等于 maxx 的话,就是 dp 增加,也就是LIS的子序列里边的序号
    {
        ans[i++]=mice[maxx].pos;// 记录到结果数组里边
        maxx=pre[maxx];
    }
    cout<<mice[maxx].pos<<endl; // 先输出LIS最后一个结尾的老鼠编号(此时已经排序好了)
    for(int j=i-1;j>=0;j--)
        cout<<ans[j]<<endl;
}

 

 

 

完全背包

 

最近xhd正在玩一款叫做FATE的游戏,为了得到极品装备,xhd在不停的杀怪做任务。久而久之xhd开始对杀怪产生的厌恶感,但又不得不通过杀怪来升完这最后一级。现在的问题是,xhd升掉最后一级还需n的经验值,xhd还留有m的忍耐度,每杀一个怪xhd会得到相应的经验,并减掉相应的忍耐度。当忍耐度降到0或者0以下时,xhd就不会玩这游戏。xhd还说了他最多只杀s只怪。请问他能升掉这最后一级吗?

输入数据有多组,对于每组数据第一行输入n,m,k,s(0 < n,m,k,s < 100)四个正整数。分别表示还需的经验值,保留的忍耐度,怪的种数和最多的杀怪数。接下来输入k行数据。每行数据输入两个正整数a,b(0 < a,b < 20);分别表示杀掉一只这种怪xhd会得到的经验值和会减掉的忍耐度。(每种怪都有无数个)

输出升完这级还能保留的最大忍耐度,如果无法升完这级输出-1。

10 10 1 10
1 1
10 10 1 9
1 1
9 10 2 10
1 1
2 2
0
-1
1

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<bits/stdc++.h>
using namespace std;
#define MAXN 110//开太大会内存超限
int dp[MAXN][MAXN];//dp[i][j]表示在i忍耐度下杀j只怪所得到的最多经验
int v[MAXN],w[MAXN];//分别表示杀掉一只这种怪xhd会得到的经验值和会减掉的忍耐度
int main()
{
    int n,m,K,s;
    while(cin>>n>>m>>K>>s)//还需的经验值 保留的忍耐度 怪的种数 最多的杀怪数
    {
        memset(dp,0,sizeof(dp));//初始化清空
        memset(a,0,sizeof(Node)*MAXN);
        int i,j,k,flag=0;
        for(i=0; i<K; ++i)
            cin>>v[i]>>w[i];//可得到的经验值和会减掉的忍耐度
        for(i=1; i<=m; ++i)//忍耐度
        {
            for(j=0; j<K; ++j)//怪的种数
                for(k=1; k<=s; ++k) //可杀怪总数
                    if(w[j]<=i)
                        dp[i][k]=max(dp[i][k],dp[i-w[j]][k-1]+v[j]);
            if(dp[i][s]>=n)
            {
                cout<<m-i<<endl;
                flag=1;
                break;
            }
        }
        if(!flag)cout<<"-1"<<endl;
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值