题目请自行搜索,来源于各个oj平台。
P1434 [SHOI2002]滑雪
标签
各省省选
上海
2002
题目描述
Michael 喜欢滑雪。这并不奇怪,因为滑雪的确很刺激。可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你。Michael 想知道在一个区域中最长的滑坡。区域由一个二维数组给出。数组的每个数字代表点的高度。下面是一个例子:
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9
一个人可以从某个点滑向上下左右相邻四个点之一,当且仅当高度会减小。在上面的例子中,一条可行的滑坡为 2424-1717-1616-11(从 2424 开始,在 11 结束)。当然 2525-2424-2323-\ldots…-33-22-11 更长。事实上,这是最长的一条。
输入格式
输入的第一行为表示区域的二维数组的行数 RR 和列数 CC。下面是 RR 行,每行有 CC 个数,代表高度(两个数字之间用 11 个空格间隔)。
输出格式
输出区域中最长滑坡的长度。
输入输出样例
输入
5 5
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9
输出
25
说明/提示
对于 100%100% 的数据,1\leq R,C\leq 1001≤R,C≤100。
//https://www.luogu.com.cn/problem/P1434
/*
滑雪题,首先这道题无明确终点,
方法1可以搜索,记得记忆化搜索。
方法2可以是dp:dp记得排序,然后每次更新dp都是从四个方向,而且四个方向本来就要求
必须是小于的才可以走,那么更新dp的第一个for从小到大即可,保证最后结果正确
*/
#include<bits/stdc++.h>
using namespace std;
int a[100][100];
int n,m;
int Back_sum;
int dp[100][100];//记录每次的最大值
int way[4][2]= {0,1,1,0,0,-1,-1,0};
void dfs(int i,int j,int sum) {
if(dp[i][j]!=1) {
Back_sum = max(Back_sum,sum-1+dp[i][j]);
return;//关键一步!!!!!!!
}
Back_sum = max(Back_sum,sum);
for(int k = 0; k < 4; k++) {
int x = i+way[k][0];
int y = j+way[k][1];//!!!坐标的位置
if(x>=0&&y>=0&&x<n&&y<m&&a[x][y]<a[i][j]) {
dfs(x,y,sum+1);//不接收Back_sum!!
}
}
}
int main() {
scanf("%d%d",&n,&m);
fill(dp[0],dp[0]+10000,1);
for(int i = 0; i < n; i++) {
for(int j = 0; j < m; j++) {
scanf("%d",&a[i][j]);
}
}
int ans=0;
for(int i = 0; i < n; i++) {
for(int j = 0; j < m; j++) {
Back_sum = 0;
dfs(i,j,1);
dp[i][j] = Back_sum;//Back_sum传出来!!!
ans = max(ans,dp[i][j]);
}
}
printf("%d\n",ans);
}
DP解法
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;//dp版
int ii,jj,maxx;
int fx[4][2]={0,1,1,0,0,-1,-1,0};
int a[105][105];
int d[105][105];
struct node
{
int i;
int j;
int x;
}n[10005];
int read()
{
int x=0;
char ch=getchar();
while(ch>'9'||ch<'0')
{
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=x*10+ch-'0';
ch=getchar();
}
return x;
}
bool cmp(node a,node b)
{
return a.x<b.x;
}
int main()
{
freopen("in.txt","r",stdin);
ii=read();
jj=read();
int tt=0;
for(int i=0;i<ii;i++)
{
for(int j=0;j<jj;j++)
{
n[tt].i=i;
n[tt].j=j;
a[i][j]=read();
n[tt].x=a[i][j];
d[i][j]=1;
tt++;
}
}
sort(n,n+tt,cmp);
for(int t=0;t<tt;t++)
{
int i=n[t].i;
int j=n[t].j;
for(int k=0;k<4;k++)
{
int f=i+fx[k][0];
int g=j+fx[k][1];
if(f>=0&&g>=0&&f<ii&&g<jj)
{
if(a[f][g]<a[i][j])
{
d[i][j]=max(d[i][j],d[f][g]+1);
}
}
}
maxx=max(maxx,d[i][j]);
}
printf("%d",maxx);
return 0;
}
简易版之最短距离
#include<iostream>
#include<cmath>
using namespace std;
int a[600];
#define maxx INFINITY
int main() {
int N;
scanf("%d",&N);
int maxans = 0;
int ans = 0;
while(N--) {
int minn = 1e+9;
int M;
scanf("%d",&M);
for(int i = 0; i < M; i++) {
scanf("%d",&a[i]);
}
for(int i = 0; i < M; i++) {
maxans = 0;
for(int j = 0; j < M; j++) {
maxans += abs(a[i]-a[j]);
}
if(maxans<minn) {
minn = maxans;
}
}
printf("%d\n",minn);
}
}
打家劫舍
class Solution {
public:
int rob(vector<int>& nums) {
int len = nums.size();
if(len == 0) return 0;
if(len ==1 ) return nums[0];
int dp[100];
dp[0] = nums[0];
dp[1] = max(dp[0],nums[1]);
for(int i = 2;i < nums.size();i++){
dp[i] = max(dp[i-1],dp[i-2]+nums[i]);
}
return dp[nums.size()-1];//!!!!!!!
}
};
P1025 数的划分
#include<iostream>
#include<bits/stdc++.h>
using namespace std;
int N;
int n,k;
int P[1000] = {0};
int total;
int countN;
//没有什么花里胡哨,这题就是按照排列的思想来就行
//万变不离其宗,只不过这里的数,不能从1开始,必须从上一位数开始
//这样的话,也不是组合,很明显了
//需要回忆的是,组合是只能拿与不拿的。
//出现重复,立马考虑排列,假如是组合,记得思考位数
//排列的话,那么只需要判断就行了,如下
void generate(int index) {
if(total < 0)
return;
if(index == k+1) {
if(total == 0) {
countN++;
}
return;
}
//下次拿只能从自己的上一位的数,大于等于地拿
//剪枝 n-total代表的是已经加的数之和, 判断剩余的数能否放进去 比如 222行 23就不行
for(int i = P[index-1]; (n-total)+i*(k-index+1) <= n; i++) {
P[index] = i;
//拿数,即减去
total -= i;
if(total < 0){
total += i;
continue;
}
generate(index+1);
total += i;
}
}
int main() {
scanf("%d%d",&n,&k);
total = n;
countN=0;
P[0] = 1;
generate(1);
printf("%d",countN);
}
数塔
扫描二维码关注公众号,回复:
10756365 查看本文章
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int a[110][110];
int main() {
int N;
int M;
scanf("%d",&M);
while(M--) {
memset(a,0,sizeof(a));
scanf("%d",&N);
for(int i =1; i<=N; i++) {
for(int j = 1; j <= i; j++) {
scanf("%d",&a[i][j]);
}
}
int dp[110][110] = {0};
for(int i =1; i<=N; i++) {
dp[N][i] = a[N][i];
}
for(int i = N -1; i>=1; i--) {
for(int j = 1; j <= i; j++) {
dp[i][j] = a[i][j] + max(dp[i+1][j],dp[i+1][j+1]);
}
}
printf("%d\n",dp[1][1]);
}
}