26.篮球练习
Description
小徐酷爱打篮球,在小学期的前两周半都在练习篮球。
今天,小徐想要练习如何突破。练习场地可由如下所示的网格图表示,图中的位置可用坐标表示。
其中A点(0,0)为小徐的起始位置,B点(n,m)为小徐想要到达的位置。
一起训练的还有场上的防守队员小彩,其位于C点。已知小徐行动时只能向右或向下前进,且当小徐相对于小彩的位置为Pi(i = 1,2…8)时,小徐会被抢断(注:在C点时同样会被抢断)。
注意,Pi坐标是会随C位置的变化而变化的,但相对位置是固定的
现在要求你计算小徐从A点到达B点且不被抢断的路径条数。假设小彩的位置是固定不动的,并不是小徐走一步小彩走一步。
Input
一行四个正整数,分别表示B点坐标和C点坐标。
Output
一个整数,表示所有的路径条数。
Hint
对于全部的数据,1≤n,m≤20,0≤ C点的横纵坐标 ≤20。
测试输入 | 期待的输出 | 时间限制 | 内存限制 | 额外进程 | |
---|---|---|---|---|---|
测试用例 1 | 以文本方式显示
| 以文本方式显示
| 1秒 | 64M | 0 |
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int is_knight_move(int x1, int y1, int x2, int y2) {
return (abs(x1-x2)==2 && abs(y1-y2)==1) || (abs(x1-x2)==1 && abs(y1-y2)==2);
}
int is_blocked(int x, int y, int Cx, int Cy) {
return (x==Cx && y==Cy) || is_knight_move(x,y,Cx,Cy);
}
long long int count_paths(int Bx, int By, int Cx, int Cy) {
long long int dp[21][21] ={0};
if (!is_blocked(0,0,Cx,Cy)) dp[0][0]=1;
for (int i=1;i<=By;i++) {
if(!is_blocked(0,i,Cx,Cy)) dp[0][i]=dp[0][i-1];
}
for (int i=1;i<=Bx;i++) {
if(!is_blocked(i,0,Cx,Cy)) dp[i][0]=dp[i-1][0];
}
for (int i=1;i<=Bx;i++) {
for(int j=1;j<=By;j++) {
if(!is_blocked(i,j,Cx,Cy)) dp[i][j]=dp[i-1][j]+dp[i][j-1];
}
}
return dp[Bx][By];
}
int main()
{
long long int Bx,By,Cx,Cy;
scanf("%lld %lld %lld %lld",&Bx,&By,&Cx,&Cy);
printf("%lld\n",count_paths(Bx,By,Cx,Cy));
return 0;
}
27. 方向标
一位木匠收到了一份木制指示牌的订单。每块木板必须与前一块垂直对齐,要么与前一个箭头对齐,要么用专门设计的螺丝固定在对面。两块木板必须重叠。木匠写下了一个整数序列来编码设计师发送的草图,但这个序列并不能确定一个唯一的模型,他已经扔掉了原始草图。对他来说,看似琐碎的任务变成了一个大拼图。
该序列(包含1+N个元素)对从符号底部到顶部的(N)个箭头进行编码。第一个元素是底部箭头左侧的位置。剩下的N个元素定义了箭头从下到上的起始位置:第i个元素是第i个箭头基所在的位置。例如,所示的两个符号(左边和右边)可以用2 6 5 1 4编码。
由于一块板必须与前一块板垂直对齐(要么与前一个箭头的底部对齐,要么与另一侧对齐),如果顺序为2 6 5 1 4 3,则第五个箭头可以用螺钉固定在1(指向右侧)或4(指向左侧),箭头底部为3。
如果顺序是2 3 1,则第二个箭头只能用螺钉固定在3处,指向左侧,因为连续的板必须重叠。
所有箭头都是相似的,设计师告诉木匠,它们的底部和底部箭头的左侧都位于不同的垂直线上,总共形成了1.(N+1)的排列。这就是为什么木匠忽略了细节,只写下排列(例如,2 6 5 1 4 3)。
给定木匠写下的数字序列,计算可以制作的方向箭头符号的数量。由于这个数字可能很大,所以必须以2147483647为模来写。序列中的第二个整数始终大于第一个整数(底部箭头始终指向右侧)。
输入
第一行具有一个整数N,第二行包含从1到N+1的整数的排列。同一行中的整数由一个空格分隔。
输出
输出具有单个行,该行具有可以由给定排列描述的不同符号的数目(模2147483647)。
注意
1<=N<=2000
代码如下:
#include <stdio.h>
#include <stdlib.h>
#define mo 2147483647
#define Num 2005
long long dp[Num][Num];
long long head[Num];
long long max(long long a, long long b)
{
if(a>b) return a;
else return b;
}
long long min(long long a,long long b)
{
if(a>b) return b;
else return a;
}
int main()
{
long long N,L,R,ans=0;
int i,j;
scanf("%lld",&N);
scanf("%lld",&head[0]);
dp[1][head[0]]=1;
for(i=1;i<=N;i++)
{
scanf("%lld",&head[i]);
for(j=0;j<N+2;j++)
{
L=min(head[i-1],j);
R=max(head[i-1],j);
if(head[i]>=R) dp[i][L]=(dp[i-1][j]+dp[i][L])%mo;
else if(head[i]<=L) dp[i][R]=(dp[i-1][j]+dp[i][R])%mo;
else
{
dp[i][L]=(dp[i-1][j]+dp[i][L])%mo;
dp[i][R]=(dp[i-1][j]+dp[i][R])%mo;
}
}
}
for(i=0;i<N+2;i++) ans=(ans+dp[N][i])%mo;
printf("%lld\n",ans);
}
28.考试
测试输入 | 期待的输出 | 时间限制 | 内存限制 | 额外进程 | |
---|---|---|---|---|---|
测试用例 1 | 以文本方式显示
| 以文本方式显示
| 1秒 | 64M | 0 |
测试用例 2 | 以文本方式显示
| 以文本方式显示
| 1秒 | 64M | 0 |
代码如下:
#include<stdio.h>
int max(int m,int n)
{
return m>n?m:n;
}
int main()
{
int n,m,i,j,ans=-1;
scanf("%d %d",&n,&m);
int t[m],w[m],dp[n+1],v[m];
for(i=0;i<=n;i++) dp[i]=0;
for(i=0;i<m;i++){
scanf("%d %d",&t[i],&w[i]);
v[i]=t[i]*w[i];
}
for(i=0;i<m;i++) for(j=n;j-t[i]>=0;j--) dp[j]=max(dp[j],dp[j-t[i]]+v[i]);
printf("%d\n",dp[n]);
}
29. 一道简单背包题
代码如下:
#include <stdio.h>
#include <stdlib.h>
#define Num 2005
int p[Num],dp[Num][Num];
int main()
{
int n,V,i,j,mod;
scanf("%d %d",&n,&V);
dp[0][0]=1;
for(i=1;i<=n;i++)
{
scanf("%d",&p[i]);
for(j=0;j<V;j++) dp[i][j]=(dp[i-1][j]+dp[i][j])%10000000;
for(j=0;j<V;j++)
{
mod=(j+p[i])%V;
dp[i][mod]=(dp[i-1][j]+dp[i][mod])%10000000;
}
}
printf("%d\n",dp[n][0]-1);
}
30. 有一个人前来买瓜
军训这么累,当然要吃瓜啦。
有一个小军前来买瓜。
众所周知,YHW水果摊里的西瓜的瓜皮子和瓜粒子都是金粒子做的。小军当然想获得尽可能多的金粒子。
一共有n个瓜,每个瓜有重量w,成熟度v,金粒子数量g。
虽然小军的钱是无限的,但他的电动车载重是有限的,因此他不能买总重量超过W的瓜。
"我开水果摊的,能卖给你生瓜蛋子? ——YHW
因此,当小军买的瓜的总成熟度小于V时,YHW并不会把瓜卖给他。
具体的:水果摊一共有n个瓜,每个瓜有重量w,成熟度v,金粒子数量g。一共有q次询问,每次询问给出两个值W、V,小军要选取n个瓜的子集,使总重量 Σw≤W,总成熟度Σv≥V,求 Σg
的最大值。
Input
第一行输入两个整数,q(1≤n≤100,1≤q≤100),代表瓜的数量和询问数量。
接下来n行,每行三个整数,第i行的三个整数为i,vi,gi(1≤wi,vi,gi≤100),分别代表第i个瓜的重量,成熟度和价值。
接下来q行,输入两个整数,V(1≤W,V≤500),代表一组询问。
Output
输出一共有q行,每行一个整数,分别代表每组询问的最大金粒子数总和,若无合法的买法则输出-1。
测试输入 | 期待的输出 | 时间限制 | 内存限制 | 额外进程 | |
---|---|---|---|---|---|
测试用例 1 | 以文本方式显示
| 以文本方式显示
| 1秒 | 64M | 0 |
代码如下:
#include <stdio.h>
#include <stdlib.h>
#define Num 505
int max(int a,int b){
return a>b?a:b;
}
int min(int a,int b){
return a<b?a:b;
}
int w[Num],v[Num],g[Num];
int main()
{
int n,q,W,V,i,j,k,o,ans;
int dp[505][505];
memset(dp,-1,sizeof(dp));
dp[0][0]=0;
scanf("%d %d",&n,&q);
for(i=0;i<n;i++) scanf("%d %d %d",&w[i],&v[i],&g[i]);
for(i=0;i<n;i++){
for(j=500;j>=0;j--){
for(k=500;k>=0;k--){
if(dp[j][k]>=0&&j+w[i]<=500) dp[j+w[i]][min(k+v[i],500)]=max(dp[j][k]+g[i],dp[j+w[i]][min(k+v[i],500)]);
}
}
}
for(o=q;o>0;o--){
scanf("%d %d",&W,&V);
ans=-1;
for(j=0;j<=W;j++){
for(k=V;k<=500;k++) ans=max(ans,dp[j][k]);
}
printf("%d\n",ans);
}
}