第一题 smax
有N个整数,排成一行。你开始在最左端的数上,每次可以选择跳3步或5步到下一个数,直至跳过所有数,你的得分就是你跳到的数的数值总和。问你能得到的最大分数是多少?
[输入格式]
第一行:一个正整数N,表示有N个整数。1<N<1000。
第二行:有N个整数,每个整数在[-100,100]范围内。
[输出格式]
一个整数,表示最大得分。
[输入样例]
6
1 7 3 9 2 5
[输出样例]
10
#include <cstdio>
using namespace std;
int array[1001];
int dp[1001];
int main(){
int n;
scanf("%d",&n);
for (int i=0;i<n;++i){
scanf("%d",&array[i]);
dp[i]=-1001;
}
/*
for (int i=0;i<n;++i){
printf("%d ",dp[i]);
}
printf("\n");
*/
//int jump3,jump5;
dp[0]=array[0];
for (int i=0;i<n;++i){
if (dp[i]==-1000){
continue;
}
if (i+3<n && dp[i+3]<array[i+3]+dp[i]){
dp[i+3]=array[i+3]+dp[i];
}
if (i+5<n && dp[i+5]<array[i+5]+dp[i]){
dp[i+5]=array[i+5]+dp[i];
}
/*
for (int i=0;i<n;++i){
printf("%d ",dp[i]);
}
printf("\n");
*/
}
int max=-2000;
for (int i=0;i<n;++i){
if (dp[i]>max){
max=dp[i];
}
}
printf("%d\n",max);
}
第二题 pmax
有一个50*50的数字矩阵,你从左下角出发,每次可以向上或向右走一步,直到走到右上角。所有走过的路上的数值的积%107为你的得分,问你最大可以得多少分?
[输入格式]
共50行,每行50个正整数 [1,10000]范围内。
[输出格式]
一个整数,表示最大得分。
正确的程序:#include <cstdio>
using namespace std;
int num[51][51];
int main(){
for (int i=0;i<50;++i){
for (int j=0;j<50;++j){
scanf("%d",&num[i][j]);
}
}
printf("%d\n",num[0][49]%107);
}
注:后期将107改成了10007。#include <iostream>
#define fin cin
#define fout cout
#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <time.h>
using namespace std;
//ifstream fin("pmax.in");
//ofstream fout("pmax.out");
int N, a[52][52], f[52][52][10007];
int main()
{
for (int i=0; i<50; i++)
for (int j=0; j<50; j++)
{
fin >> a[i][j];
a[i][j] %=10007;
}
f[49][0][ a[49][0] ] = 1;
for (int i=49; i>=0; i--)
for (int j=0; j<50; j++)
for (int k=0; k<10007; k++)
if (f[i][j][k] >0 )
{
if (i>0 ) f[i-1][j] [ k*a[i-1][j] %10007 ] =1;
if (j<49 ) f[i][j+1] [ k*a[i][j+1] %10007 ] =1;
}
for (int i=10006; i>=0; i--)
if ( f[0][49][i] >0 )
{
fout << i<<endl;
break;
}
return 0;
}
4.守望者的逃离(escape)
【问题描述】
恶魔猎手尤迫安野心勃勃.他背叛了暗夜精灵,率深藏在海底的那加企图叛变:守望者在与尤迪安的交锋中遭遇了围杀.被困在一个荒芜的大岛上。为了杀死守望者,尤迪安开始对这个荒岛施咒,这座岛很快就会沉下去,到那时,岛上的所有人都会遇难:守望者的跑步速度,为17m/s, 以这样的速度是无法逃离荒岛的。庆幸的是守望者拥有闪烁法术,可在1s内移动60m,不过每次使用闪烁法术都会消耗魔法值10点。守望者的魔法值恢复的速度为4点/s,只有处在原地休息状态时才能恢复。
现在已知守望者的魔法初值M,他所在的初始位置与岛的出口之间的距离S,岛沉没的时间T。你的任务是写一个程序帮助守望者计算如何在最短的时间内逃离荒岛,若不能逃出,则输出守望者在剩下的时间内能走的最远距离。注意:守望者跑步、闪烁或休息活动均以秒(s)为单位。且每次活动的持续时间为整数秒。距离的单位为米(m)。
【输入格式】
输入数据仅一行,包括空格隔开的三个非负整数M,S,T。
【输出格式】
输出数据包含两行;
第1行为字符串“Yes”或“No” (区分大小写),即守望者是否能逃离荒岛;
第2行包含一个整数,当第一行为“Yes”(区分大小写)时表示守望着逃离荒岛的最短时间 ,当第一行为“No” (区分大小写) 时表示守望者能走的最远距离。
【输入输出样例】
| 输入 | 输出 |
样例1 | 39 200 4 | No 197 |
样例2 | 36 255 10 | Yes 6 |
【数据规模】
30%的数据满足: 1≤T≤10, 1≤S≤100 ;
50%的数据满足: 1≤T≤1000, 1≤S≤10000;
100%的数据满足: 1≤T≤300000, 0≤M≤1000, 1≤S≤108。
#include <cstdio>
#include<iostream>
using namespace std;
int Mana, Space, Timeleft;
int main()
{
freopen("escape.in", "r", stdin);
freopen("escape.out", "w", stdout);
scanf("%d %d %d", &Mana, &Space, &Timeleft);
int SpaceHaveSpend = 0, TimeHaveSpend = Timeleft;
while(Mana >= 10 && Timeleft > 0 && Space - SpaceHaveSpend > 0) //有魔法直接用
{
if(Space - SpaceHaveSpend > 17)
{
SpaceHaveSpend += 60;
Mana -= 10;
Timeleft--;
}
else printf("Yes\n%d", TimeHaveSpend - Timeleft - 1); //若魔法用完后直接到达,则结束
}
while(Timeleft > 0 && Space - SpaceHaveSpend > 0)
{
if((Mana == 0 || Mana == 1) && Timeleft >= 7 && Space - SpaceHaveSpend > 102)
{
Timeleft -= 7; //等五次,闪两次,
SpaceHaveSpend += 120;
}
else if(Mana >= 2 && Mana <= 5 && Timeleft >= 3 && Space - SpaceHaveSpend > 34) //等两次,闪一次
{
Mana -= 2;
Timeleft -= 3;
SpaceHaveSpend += 60;
}
else if(Mana >= 6 && Timeleft >= 2 && Space - SpaceHaveSpend > 17) //等一次,闪一次
{
Mana -= 6;
Timeleft -= 2;
SpaceHaveSpend += 60;
}
else
{
SpaceHaveSpend += 17; //其他情况直接走
Timeleft--;
}
}
if(Space <= SpaceHaveSpend) printf("Yes\n%d", TimeHaveSpend - Timeleft); //输出答案
else printf("No\n%d", SpaceHaveSpend);
return 0;
}
1004:gold
时间:2015.8.4
1. 抢金块(gold)
【问题描述】
地面上有一些格子,每个格子上面都有金块,但不同格子上的金块有不同的价值,你一次可以跳S至T步 (2≤S<T≤10) 如果S=2,T=4。你就可以跳2步、3步或4步,告诉你这些后,你从第一个格子起跳,必须跳到最后一个格子上,请你输出最多可以获得的金块的总价值。
【输入格式】
第一行是格子个数;
第二行是S和T ,保证T大于S;
第三行是每个格子上的金块价值。第一个为第一个格子上的价值,默认从第一个格子起跳,必须跳到最后一个格子上,也就是说第一个格子上的金块和最后一个格子的金块你就可以直接获得了。
【输出格式】
输出最多可以获得的金块的总价值。
【输入样例】
10
2 3
4 5 8 2 8 3 6 7 2 9
【输出样例】
36
样例说明:
跳1、3、5、8、10
总价值:4+8+8+7+9=36
【数据规模】
格子数目<1000;
2≤S<T≤10;
每个金块的价值<10000。
#include <cstdio>
using namespace std;
int num[1001];
int dp[1001];
int main(){
freopen("gold.in","r",stdin);
freopen("gold.out","w",stdout);
int n;
int s,t;
scanf("%d",&n);
scanf("%d %d",&s,&t);
for (int i=0;i<n;++i){
scanf("%d",&num[i]);
dp[i]=-0x7ffff;
}
dp[0]=num[0];
for (int i=0;i<n;++i){
if (dp[i]==-0x7ffff){ continue; }
for (int j=s;j<=t;++j){
if (dp[i]+num[i+j]>dp[i+j]){
dp[i+j]=dp[i]+num[i+j];
}
}
}
/*
int max=dp[0];
for (int i=1;i<n;++i){
if (dp[i]>max){
max=dp[i];
}
}
*/
/*
for (int i=0;i<n;++i){
printf("%d ",dp[i]);
}
*/
// printf("\n");
printf("%d\n",dp[n-1]);
}
1005:chorus
时间:2015.8.4.
2.合唱队形(chorus)
【问题描述】
N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队形。
合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2…,K,他们的身高分别为T1,T2,…,TK, 则他们的身高满足T1<... <Ti> Ti+1>…>TK(1≤i≤K)。
你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。
【输入格式】
输入的第一行是一个整数N(2≤N≤100),表示同学的总数。第一行有n个整数,用空格分隔,第i个整数Ti(130≤Ti≤230)是第i位同学的身高(厘米)。
【输出格式】
输出包括一行,这一行只包含一个整数,就是最少需要几位同学出列。
【输入样例】
8
186 186 150 200 160 130 197 220
【输出样例】
4
【数据规模】
对于50%的数据,保证有n≤20;
对于全部的数据,保证有n≤100。
#include <stdio.h>
#include <string.h>
int hei[101], ldp[101], rdp[101];
int main()
{
freopen("chorus.in", "r", stdin);
freopen("chorus.out", "w", stdout);
int n;
while(scanf("%d", &n) != EOF)
{
if(n == -1) break;
int i;
memset(ldp, 0, sizeof(ldp));
for(i = 1; i <= n; i++)
{
scanf("%d", &hei[i]);
ldp[i] = 1;
}
int j;
for(i = 1; i <= n; i++)
{
for(j = i - 1; j >= 0; j--)
{
if(hei[j] < hei[i] && ldp[i] < ldp[j] + 1)
{
ldp[i] = ldp[j] + 1;
}
}
}
memset(rdp, 0, sizeof(rdp));
for(i = 1; i <= n; i++)
{
rdp[i] = 1;
}
for(i = n; i >= 1; i--)
{
for(j = i + 1; j <= n; j++)
{
if(hei[j] < hei[i] && rdp[i] < rdp[j] + 1)
{
rdp[i] = rdp[j] + 1;
}
}
}
int max = 0;
for(i = 1; i <= n; i++)
{
if(rdp[i] + ldp[i] > max)
{
max = rdp[i] + ldp[i];
}
}
max--;
printf("%d\n", n - max);
}
return 0;
}
Still