暑假集训-训练6 动态规划初步

A - 爬楼梯
Time Limit:1000MS Memory Limit:131072KB 64bit IO Format:%lld & %llu
Submit

Status
Description
小时候我们都玩过爬楼梯的游戏:两人猜拳,赢了可向上爬一级,谁先到最高级则获胜。作为大学生,我们应该玩一个更有水平的游戏。
现在一个人要上n级楼梯,每一步可以选择上一级或者上两级,但是不能后退。求上这n级楼梯的方案数。

Input
第一行只有一个整数T(1<=T<=45),表示数据组数。
下面的T行每一行有一个整数n(1<=n<=45),表示有多少级楼梯。

Output
对于每一组数据输出一个整数s,表示方案数。

Sample Input
4
1
2
3
4
Sample Output
1
2
3
5

A:爬楼梯

#include<stdio.h>
#include<string>
#include<cstring>
#include<queue>
#include<algorithm>
#include<functional>
#include<vector>
#include<iomanip>
#include<math.h>
#include<iostream>
#include<sstream>
#include<set>
using namespace std;
const int MAX=45+5;
int F[MAX];
int main()
{
    F[1]=1;
    F[2]=2;
    for (int i=3;i<=46;i++)
    {
        F[i]=F[i-1]+F[i-2];
    }
    int T,N;
    cin>>T;
    while (T--)
    {
        cin>>N;
        cout<<F[N]<<endl;
    }
    return 0;
}

B - Critical Mass
Time Limit:3000MS Memory Limit:0KB 64bit IO Format:%lld & %llu

During the early stages of the Manhattan Project, the dangers of the new radioctive materials were
not widely known. Vast new factory cities were built to manufacture uranium and plu- tonium in bulk.
Compounds and solutions of these substances were accumulating in metal barrels, glass bottles and
cardboard box piles on the cement floors of store rooms. Workers did not know that the substances they
were handling could result in sickness, or worse, an explosion. The officials who new the danger assumed
that they could ensure safety by never assembling any amount close to the critical mass estimated by
the physicists. But mistakes were made. The workers, ignorant of the the dangers, often did not track
these materials carefully, and in some cases, too much material was stored together — an accident was
waiting to happen.
Fortunately, the dangers were taken seriously by a few knowledgeable physicists. They drew up
guidelines for how to store the materials to eliminate the danger of critical mass accumulations. The
system for handling uranium was simple. Each uranium cube was marked “U”. It was to be stacked
with lead cubes (marked “L”) interspersed. No more than two uranium cubes could be next to each
other on a stack. With this simple system, a potential for the uranium reaching critical mass (three
stacked next to each other) was avoided. The second constraint is that no more than thirty cubes can
be stacked on top of each other, since the height of the storage room can only accommodate that many.
One of the physicists was still not completely satisfied with this solution. He felt that a worker, not
paying attention or not trained with the new system, could easily cause a chain reaction. He posed
the question: consider a worker stacking the radioactive cubes and non radioactive cubes at random
on top of each other to a height of n cubes; how many possible combinations are there for a disaster to
happen?
For example, say the stack is of size 3. There is one way for the stack to reach critical mass — if
all three cubes are radioactive.
1: UUU
However, if the size of the stack is 4, then there are three ways:
1: UUUL
2: LUUU
3: UUUU
Input
The input is a list of integers on separate lines. Each integer corresponds to the size of the stack and
is always greater than 0. The input is terminated with a integer value of ‘0’.
Output
For each stack, compute the total number of dangerous combinations where each cube position in the
linear stack can either be “L” for lead, or “U” for uranium. Output your answer as a single integer on
a line by itself.
Sample Input
4
5
0
Sample Output
3
8


B:


#include<stdio.h>
#include<string>
#include<cstring>
#include<queue>
#include<algorithm>
#include<functional>
#include<vector>
#include<iomanip>
#include<math.h>
#include<iostream>
#include<sstream>
#include<set>
using namespace std;
const int UU=0;
const int UL=1;
const int LU=2;
const int LL=3;
int F[4][35]={0};
int main()
{
    F[UU][2]=1;F[UL][2]=1;F[LU][2]=1;F[LL][2]=1;
    for (int i=3;i<=30;i++)
    {
        F[UU][i]=F[LU][i-1];
        F[UL][i]=F[UU][i-1]+F[LU][i-1];
        F[LU][i]=F[LL][i-1]+F[UL][i-1];
        F[LL][i]=F[UL][i-1]+F[LL][i-1];
    }
    int n;
    while(cin>>n&&n)
    {
        if (n<3)
        {
            cout<<0<<endl;
            continue;
        }
        int ans=1<<n;
        for (int i=0;i<4;i++)
            ans-=F[i][n];
        cout<<ans<<endl;
    }
    return 0;
}

C - Race
Time Limit:1000MS Memory Limit:0KB 64bit IO Format:%lld & %llu

Disky and Sooma, two of the biggest mega minds of Bangladesh went to a far country. They ate, coded
and wandered around, even in their holidays. They passed several months in this way. But everything
has an end. A holy person, Munsiji came into their life. Munsiji took them to derby (horse racing).
Munsiji enjoyed the race, but as usual Disky and Sooma did their as usual task instead of passing some
romantic moments. They were thinking- in how many ways a race can finish! Who knows, maybe this
is their romance!
In a race there are n horses. You have to output the number of ways the race can finish. Note that,
more than one horse may get the same position. For example, 2 horses can finish in 3 ways.
1. Both first
2. horse1 first and horse2 second
3. horse2 first and horse1 second
Input
Input starts with an integer T (≤ 1000), denoting the number of test cases. Each case starts with a
line containing an integer n (1 ≤ n ≤ 1000).
Output
For each case, print the case number and the number of ways the race can finish. The result can be
very large, print the result modulo 10056.
Sample Input
3
1
2
3
Sample Output
Case 1: 1
Case 2: 3
Case 3: 13


C: 紫书332页 

#include<stdio.h>
#include<string>
#include<cstring>
#include<queue>
#include<algorithm>
#include<functional>
#include<vector>
#include<iomanip>
#include<math.h>
#include<iostream>
#include<sstream>
#include<set>
using namespace std;
const int MAX=1000+2;
const int MOD=10056;
int F[MAX],C[MAX][MAX];
int main()
{
    memset(C,0,sizeof(C));
    for (int i=0;i<=1000;i++)
    {
        C[i][0]=1;
        for (int j=1;j<=i;j++)
            C[i][j]=(C[i-1][j-1]+C[i-1][j])%MOD;
    }
    F[0]=1;
    F[1]=1;
    for (int i=2; i<=1000; i++)
    {
        F[i]=0;
        for (int j=1; j<=i; j++)
        {
            F[i]=(F[i]+(C[i][j]*F[i-j])%MOD)%MOD;
        }
    }
    int T;
    cin>>T;
    for (int a=1;a<=T;a++)
    {
        int n;
        cin>>n;
        cout<<"Case "<<a<<": "<<F[n]<<endl;
    }
    return 0;
}

D - 数字三角
Time Limit:0MS Memory Limit:0KB 64bit IO Format:%lld & %llu
Submit

Status
Description
下图是个数字三角,请编写一个程序计算从顶部至底部某处一条路径,使得该路径所经过的数字总和最大。
7
3 8
8 1 0
2 7 4 4
1. 每一步可沿左斜线向下或右斜线向下走;
2. 1<=三角形行数<=100
3. 三角形中的数字为整数 0,1,……,99。
4. 如果有多种情况结果都最大,任意输出一种即可。

输入:
第一行一个整数N,代表三角形的行数。
接下来N行,描述了一个数字三角。

输出:
第一行一个整数,代表路径所经过底数字总和。
第二行N个数,代表所经过的数字。

样例:
输入:
4
7
3 8
8 1 0
2 7 4 4
输出:
25
7 3 8 7

注意要打印路径



D:数字三角形


#include<stdio.h>
#include<string>
#include<cstring>
#include<queue>
#include<algorithm>
#include<functional>
#include<vector>
#include<iomanip>
#include<math.h>
#include<iostream>
#include<sstream>
#include<set>
using namespace std;
const int MAX=100+5;
int pic[MAX][MAX];
int F[MAX][MAX];
int main()
{
    int n;
    while(cin>>n)
    {
        memset(F,0,sizeof(F));
        memset(pic,0,sizeof(pic));
        for (int i=1;i<=n;i++)
        {
            for (int j=1;j<=i;j++)
            {
                cin>>pic[i][j];
            }
        }
        for (int j=1;j<=n;j++) F[n][j]=pic[n][j];
        for (int i=n-1;i>=1;i--)
        {
            for (int j=1;j<=i;j++)
            {
                F[i][j]=max(F[i+1][j],F[i+1][j+1])+pic[i][j];
            }
        }
        cout<<F[1][1]<<endl<<pic[1][1];
        for (int i=2,j=1;i<=n;i++)
        {
            if (F[i][j]>F[i][j+1])
            {
                cout<<' '<<pic[i][j];
            }
            else
            {
                j+=1;
                cout<<' '<<pic[i][j];
            }
        }
        cout<<endl;
    }
}

E - Common Subsequence
Time Limit:1000MS Memory Limit:10000KB 64bit IO Format:%lld & %llu
Submit

Status
Description
A subsequence of a given sequence is the given sequence with some elements (possible none) left out. Given a sequence X = < x1, x2, …, xm > another sequence Z = < z1, z2, …, zk > is a subsequence of X if there exists a strictly increasing sequence < i1, i2, …, ik > of indices of X such that for all j = 1,2,…,k, x ij = zj. For example, Z = < a, b, f, c > is a subsequence of X = < a, b, c, f, b, c > with index sequence < 1, 2, 4, 6 >. Given two sequences X and Y the problem is to find the length of the maximum-length common subsequence of X and Y.
Input
The program input is from the std input. Each data set in the input contains two strings representing the given sequences. The sequences are separated by any number of white spaces. The input data are correct.
Output
For each set of data the program prints on the standard output the length of the maximum-length common subsequence from the beginning of a separate line.
Sample Input
abcfbc abfcab
programming contest
abcd mnp
Sample Output
4
2
0


E:最长公共自序列

#include<stdio.h>
#include<string>
#include<cstring>
#include<queue>
#include<algorithm>
#include<functional>
#include<vector>
#include<iomanip>
#include<math.h>
#include<iostream>
#include<sstream>
#include<set>
using namespace std;
const int MAX=1000+5;
int F[MAX][MAX];
int main()
{
    string a,b;
    while (cin>>a>>b)
    {
        memset(F,0,sizeof(F));
        for (int i=1;i<=a.length();i++)
        {
            for (int j=1;j<=b.length();j++)
            {
                if (a[i-1]==b[j-1]) F[i][j]=F[i-1][j-1]+1;
                else F[i][j]=max(F[i-1][j],F[i][j-1]);
            }
        }
        cout<<F[a.length()][b.length()]<<endl;
    }
    return 0;
}

F - Longest Ordered Subsequence
Time Limit:2000MS Memory Limit:65536KB 64bit IO Format:%lld & %llu
Submit

Status
Description
A numeric sequence of ai is ordered if a1 < a2 < … < aN. Let the subsequence of the given numeric sequence ( a1, a2, …, aN) be any sequence ( ai1, ai2, …, aiK), where 1 <= i1 < i2 < … < iK <= N. For example, sequence (1, 7, 3, 5, 9, 4, 8) has ordered subsequences, e. g., (1, 7), (3, 4, 8) and many others. All longest ordered subsequences are of length 4, e. g., (1, 3, 5, 8).

Your program, when given the numeric sequence, must find the length of its longest ordered subsequence.
Input
The first line of input file contains the length of sequence N. The second line contains the elements of sequence - N integers in the range from 0 to 10000 each, separated by spaces. 1 <= N <= 1000
Output
Output file must contain a single integer - the length of the longest ordered subsequence of the given sequence.
Sample Input
7
1 7 3 5 9 4 8
Sample Output
4


F:最长上升自序列

#include<stdio.h>
#include<string>
#include<cstring>
#include<queue>
#include<algorithm>
#include<functional>
#include<vector>
#include<iomanip>
#include<math.h>
#include<iostream>
#include<sstream>
#include<set>
using namespace std;
const int MAX=1000+5;
int a[MAX];
int F[MAX];
int main()
{
    int N;
    while (cin>>N)
    {
        memset(F,0,sizeof(F));
        memset(a,0,sizeof(a));
        for (int i=1; i<=N; i++) cin>>a[i];
        F[1]=1;
        int ans=1;
        int m=0;
        for (int i=1; i<=N; i++)
        {
            m=0;
            for (int j=1; j<i; j++)
            {
                if (a[j]<a[i]) m=max(m,F[j]);
            }
            F[i]=m+1;
            ans=max(ans,F[i]);
        }
        cout<<ans<<endl;
    }
    return 0;
}

G - Jin Ge Jin Qu hao
Time Limit:1000MS Memory Limit:0KB 64bit IO Format:%lld & %llu

(If you smiled when you see the title, this problem is for you ^_^)
For those who don’t know KTV, see: http://en.wikipedia.org/wiki/Karaoke_box
There is one very popular song called Jin Ge Jin Qu(). It is a mix of 37 songs, and is extremely
long (11 minutes and 18 seconds) — I know that there are Jin Ge Jin Qu II and III, and some other
unofficial versions. But in this problem please forget about them.
Why is it popular? Suppose you have only 15 seconds left (until your time is up), then you should
select another song as soon as possible, because the KTV will not crudely stop a song before it ends
(people will get frustrated if it does so!). If you select a 2-minute song, you actually get 105 extra
seconds! ….and if you select Jin Ge Jin Qu, you’ll get 663 extra seconds!!!
Now that you still have some time, but you’d like to make a plan now. You should stick to the
following rules:
• Don’t sing a song more than once (including Jin Ge Jin Qu).
• For each song of length t, either sing it for exactly t seconds, or don’t sing it at all.
• When a song is finished, always immediately start a new song.
Your goal is simple: sing as many songs as possible, and leave KTV as late as possible (since we
have rule 3, this also maximizes the total lengths of all songs we sing) when there are ties.
Input
The first line contains the number of test cases T (T ≤ 100). Each test case begins with two positive
integers n, t (1 ≤ n ≤ 50, 1 ≤ t ≤ 109
), the number of candidate songs (BESIDES Jin Ge Jin Qu)
and the time left (in seconds). The next line contains n positive integers, the lengths of each song, in
seconds. Each length will be less than 3 minutes — I know that most songs are longer than 3 minutes.
But don’t forget that we could manually “cut” the song after we feel satisfied, before the song ends.
So here “length” actually means “length of the part that we want to sing”.
It is guaranteed that the sum of lengths of all songs (including Jin Ge Jin Qu) will be strictly larger
than t.
Output
For each test case, print the maximum number of songs (including Jin Ge Jin Qu), and the total lengths
of songs that you’ll sing.
Explanation:
In the first example, the best we can do is to sing the third song (80 seconds), then Jin Ge Jin Qu
for another 678 seconds.
In the second example, we sing the first two (30+69=99 seconds). Then we still have one second
left, so we can sing Jin Ge Jin Qu for extra 678 seconds. However, if we sing the first and third song
instead (30+70=100 seconds), the time is already up (since we only have 100 seconds in total), so we
can’t sing Jin Ge Jin Qu anymore!
Sample Input
2
3 100
60 70 80
3 100
30 69 70
Sample Output
Case 1: 2 758
Case 2: 3 777


G:  首先曲目最多 其次时间最长 . F记录次数 G记录时间


#include<stdio.h>
#include<string>
#include<cstring>
#include<queue>
#include<algorithm>
#include<functional>
#include<vector>
#include<iomanip>
#include<math.h>
#include<iostream>
#include<sstream>
#include<set>
using namespace std;
const int MAX=50+5;
int F[MAX*180+678],G[MAX*180+678],A[MAX];
int n,t,T;
void ZeroOnePack(int ci,int wi)
{
    for (int i=t; i>=ci; i--)
    {
        if (F[i]<F[i-ci]+wi)
        {
            F[i]=F[i-ci]+wi;
            G[i]=G[i-ci]+ci;
        }
        else if (F[i]==F[i-ci]+1)
        {
            G[i]=max(G[i],G[i-ci]+ci);
        }
    }
}
int main()
{
    cin>>T;
    int cases=0;
    while (T--)
    {
        cases++;
        memset(F,0,sizeof(F));
        memset(G,0,sizeof(G));
        cin>>n>>t;
        t-=1;
        for (int i=1; i<=n; i++) cin>>A[i];
        for (int i=1; i<=n; i++)
            ZeroOnePack(A[i],1);
        cout<<"Case "<<cases<<": "<<(F[t]+1)<<" "<<(G[t]+678)<<endl;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值