洛谷P1002 [NOIP2002 普及组] 过河卒
题目描述
棋盘上 AA 点有一个过河卒,需要走到目标 BB 点。卒行走的规则:可以向下、或者向右。同时在棋盘上 CC 点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点。因此称之为“马拦过河卒”。
棋盘用坐标表示,AA 点 (0, 0)(0,0)、BB 点 (n, m)(n,m),同样马的位置坐标是需要给出的。
现在要求你计算出卒从 AA 点能够到达 BB 点的路径的条数,假设马的位置是固定不动的,并不是卒走一步马走一步。
输入格式
一行四个正整数,分别表示 BB 点坐标和马的坐标。
输出格式
一个整数,表示所有的路径条数。
输入输出样例
输入 #1复制
6 6 3 3
输出 #1复制
6
说明/提示
对于 100 \%100% 的数据,1 \le n, m \le 201≤n,m≤20,0 \le0≤ 马的坐标 \le 20≤20。
【题目来源】
NOIP 2002 普及组第四题
#include<bits/stdc++.h>
using namespace std;
long long a[30][30];
//long long b[30][30];
int main(){
int c[9]={1,-1,-1,3,3,0,0,2,2};
int d[9]={1,0,2,0,2,-1,3,3,-1};
long long n;
//long long a[30][30]={0};
int x1,x2,y1,y2;
cin>>x2>>y2>>x1>>y1;
for(int i=0;i<9;i++){
if(x1+c[i]<1 || y1+d[i]<1)
continue;
a[x1+c[i]][y1+d[i]]=-1;
}
a[1][1]=1;
for(int i=1;i<=x2+1;i++){
for(int j=1;j<=y2+1;j++){
if(a[i][j]==-1)
a[i][j]=0;
else{
a[i][j]+=a[i-1][j]+a[i][j-1];
}
}
}
cout<<a[x2+1][y2+1];
return 0;
}
洛谷P1164 小A点菜
题目背景
uim 神犇拿到了 uoi 的 ra(镭牌)后,立刻拉着基友小 A 到了一家……餐馆,很低端的那种。
uim 指着墙上的价目表(太低级了没有菜单),说:“随便点”。
题目描述
不过 uim 由于买了一些书,口袋里只剩 MM 元 (M \le 10000)(M≤10000)。
餐馆虽低端,但是菜品种类不少,有 NN 种 (N \le 100)(N≤100),第 ii 种卖 a_iai 元 (a_i \le 1000)(ai≤1000)。由于是很低端的餐馆,所以每种菜只有一份。
小 A 奉行“不把钱吃光不罢休”,所以他点单一定刚好把 uim 身上所有钱花完。他想知道有多少种点菜方法。
由于小 A 肚子太饿,所以最多只能等待 11 秒。
输入格式
第一行是两个数字,表示 NN 和 MM。
第二行起 NN 个正数 a_iai(可以有相同的数字,每个数字均在 10001000 以内)。
输出格式
一个正整数,表示点菜方案数,保证答案的范围在 int 之内。
输入输出样例
输入 #1复制
4 4 1 1 2 2
输出 #1复制
3
#include<bits/stdc++.h>
using namespace std;
int a[120],b[120][12000];
int main(){
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
if(j==a[i]){
b[i][j]=b[i-1][j]+1;
}
if(j>a[i]){
b[i][j]=b[i-1][j]+b[i-1][j-a[i]];
}
if(j<a[i]) {
b[i][j]=b[i-1][j];
}
}
cout<<b[n][m];
return 0;
}
牛客清楚姐姐学01背包(Easy Version)
题目描述
本题有对应的hard version,区别仅在于数据范围,见输入描述,保证easy version的测试用例集是hard version的子集。
请确保在尝试本题时了解动态规划中01背包的相关内容。
如不了解动态规划或者01背包算法,可以到oiwiki进行学习了解后再尝试本题。
动态规划:https://oi-wiki.org//dp/
01背包:https://oi-wiki.org//dp/knapsack/#0-1-%E8%83%8C%E5%8C%85
清楚姐姐最近学会了01背包,01背包是背包问题中最简单的问题。
01背包的约束条件是给定几种物品,每种物品有且只有一个,并且有权值和体积两个属性。在01背包问题中,因为每种物品只有一个,对于每个物品只需要考虑选与不选两种情况。
如果不选择将其放入背包中,则不需要处理。如果选择将其放入背包中,由于不清楚之前放入的物品占据了多大的空间,需要枚举将这个物品放入背包后可能占据背包空间的所有情况。
现在清楚姐姐有NN个蝴蝶结,第ii个蝴蝶结的体积为w_{i}w
i
,好看程度为v_{i}v
i
,她准备了一个容量大小为MM的包包。她可以从这NN个蝴蝶结中任选若干个放入背包,但是所选蝴蝶结的体积总和不能大于背包的容量MM,清楚姐姐想要让所选蝴蝶结的好看程度总和最大化。
她运用自己刚刚学会的01背包知识,快速算出了她能用她的包包装下蝴蝶结好看程度总和的最大值。
现在清楚姐姐有了一个新的问题,我们定义原问题的答案,即所选蝴蝶结好看程度总和的最大值为Val_{max}Val
max
。
定义从这NN个蝴蝶结中去掉第ii个蝴蝶结后,从剩余N-1N−1个蝴蝶结中任选若干个放入背包,所选蝴蝶结好看程度总和的最大值为Val'_{i}Val
i
′
。
若Val'_{i}<Val_{max}Val
i
′
<Val
max
,则称第ii个蝴蝶结为一个“必选蝴蝶结”。
清楚姐姐现在获得了调整蝴蝶结好看程度的机会,她想要知道,对于第ii个蝴蝶结,在它初始好看程度的基础上,再加上多少,该蝴蝶结就能够成为一个“必选蝴蝶结”。
输入描述:
第一行输入两个正整数N,M(1 \leq N,M \leq 100)N,M(1≤N,M≤100)。
接下来NN行,每行输入两个正整数w_i,v_i(1 \leq w_i \leq M, v_i \leq 10^9)w
i
,v
i
(1≤w
i
≤M,v
i
≤10
9
)表示每个蝴蝶结的体积以及好看程度
输出描述:
输出NN行,每行一个整数,第ii行表示在它初始好看程度的基础上,再加上多少,该蝴蝶结就能够成为一个“必选蝴蝶结”。特别的,如果该蝴蝶结已经是一个“必选蝴蝶结”,则输出00。
示例1
输入
复制
4 100
100 100
99 10
1 2
5 5
输出
复制
0
89
89
94
示例2
输入
复制
3 1
1 100
1 100
1 100
输出
复制
1
1
1
说明
注意只有当Val'_{i}<Val_{max}Val
i
′
<Val
max
时,才称其为“必选蝴蝶结”,与原本的最大值完全相等时说明该蝴蝶结的好看程度还需要再加上11点。
#include<bits/stdc++.h>
using namespace std;
long long zui[2000];
int main(){
long long v,n,a[2000],b[2000],g=0,l[2000],h;
cin>>n>>v;
for(int j=0;j<n;j++){
cin>>a[j]>>b[j];
for(int i=v;i>=a[j];i--){
zui[i]=max(zui[i],zui[i-a[j]]+b[j]);
}
}
h=zui[v];
while(g<n){
for(int i=0;i<=v;i++){
zui[i]=0;
}
for(int j=0;j<n;j++){
if(j==g)
continue;
for(int i=v;i>=a[j];i--){
zui[i]=max(zui[i],zui[i-a[j]]+b[j]);
}
}
if(zui[v]<h)
cout<<0<<'\n';
else{
l[g]=v-a[g];
cout<<h-zui[l[g]]+1-b[g]<<'\n';
}
g++;
}
return 0;
}