luoguP1001~P1005

这是一个标准代码的模板

#include<iostream>
using namespace std;
int main()
{
    return 0;
}

下面有一些例题

1. P1001 A+B

题目描述

输入两个整数 a,b,输出它们的和(∣a∣,∣b∣≤10^9)。

输入格式

两个整数以空格分开。

输出格式

一个整数。

输入输出样例

输入 #1

1 2

输出 #1

3

代码

#include <iostream>
using namespace std;
int main() 
{
    int a,b;
    cin >> a >> b;
    cout << a+b;
    return 0;
}

2.P1002过河卒

题目描述

棋盘上 A 点有一个过河卒,需要走到目标 B* 点。卒行走的规则:可以向下、或者向右。同时在棋盘上 C* 点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点。因此称之为“马拦过河卒”。

棋盘用坐标表示,A* 点 (0,0)、B 点(n,m),同样马的位置坐标是需要给出的。

img

现在要求你计算出卒从 A* 点能够到达 B* 点的路径的条数,假设马的位置是固定不动的,并不是卒走一步马走一步。

输入格式

一行四个正整数,分别表示 B* 点坐标和马的坐标。

输出格式

一个整数,表示所有的路径条数。

输入输出样例

输入 #1

6 6 3 3

输出 #1

6

说明/提示

对于 100% 的数据,1≤n,m≤20,0 ≤ 马的坐标 ≤20。

代码

// luogu-judger-enable-o2
#include<cstdio>
const int Const[2][9]={{0,-2,-1,1,2,2,1,-1,-2},{0,1,2,2,1,-1,-2,-2,-1}};
long long DP[21][21]={1};
bool mark[21][21];
int main() {
    int nx,ny,hx,hy;
    scanf("%d%d%d%d",&nx,&ny,&hx,&hy);
    for(int i=0;i<9;++i)
        if(hx+Const[0][i]>=0&&hx+Const[0][i]<=nx&&hy+Const[1][i]>=0&&hy+Const[1][i]<=ny)
            mark[hx+Const[0][i]][hy+Const[1][i]]=1;
    for(int i=0;i<=nx;++i)
        for(int j=0;j<=ny;++j) {
            if(i)
                DP[i][j]+=DP[i-1][j];
            if(j)
                DP[i][j]+=DP[i][j-1];
            DP[i][j]*=!mark[i][j];
        }
    printf("%lld",DP[nx][ny]);
    return 0;
}

3.P1003铺地毯

题目描述

为了准备一个独特的颁奖典礼,组织者在会场的一片矩形区域(可看做是平面直角坐标系的第一象限)铺上一些矩形地毯。一共有 n 张地毯,编号从 1 到 n*。现在将这些地毯按照编号从小到大的顺序平行于坐标轴先后铺设,后铺的地毯覆盖在前面已经铺好的地毯之上。

地毯铺设完成后,组织者想知道覆盖地面某个点的最上面的那张地毯的编号。注意:在矩形地毯边界和四个顶点上的点也算被地毯覆盖。

输入格式

输入共 n*+2 行。

第一行,一个整数 n*,表示总共有 n* 张地毯。

接下来的 n* 行中,第 i+1 行表示编号 ii 的地毯的信息,包含四个整数 a*,b,g,k,每两个整数之间用一个空格隔开,分别表示铺设地毯的左下角的坐标 (a,b) 以及地毯在 x* 轴和 y 轴方向的长度。

第 n+2 行包含两个整数 x 和 y,表示所求的地面的点的坐标 (x, y)(x,y)。

输出格式

输出共 1 行,一个整数,表示所求的地毯的编号;若此处没有被地毯覆盖则输出 -1

输入输出样例

输入 #1

3
1 0 2 3
0 2 3 3
2 1 3 3
2 2

输出 #1

3

输入 #2

3
1 0 2 3
0 2 3 3
2 1 3 3
4 5

输出 #2

-1

说明/提示

【样例解释 1】

如下图,1 号地毯用实线表示,2 号地毯用虚线表示,3 号用双实线表示,覆盖点 (2,2) 的最上面一张地毯是 3 号地毯。

img

在这里插入图片描述

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
int main()
{
	int n;
	cin>>n;
	int a[n][4];
	for(int i=0;i<n;i++)
	{
		cin>>a[i][0]>>a[i][1]>>a[i][2]>>a[i][3];
	}
	int x,y;
	cin>>x>>y;
	int sum=-1;
	for(int i=0;i<n;i++)
	{
		if(x>=a[i][0]&&x<=a[i][0]+a[i][2]&&y>=a[i][1]&&y<=a[i][1]+a[i][3])
		{
			sum=i+1;
		}
	}
	cout<<sum; 
}

4.P1004 方格取数

题目描述

设有 N×N* 的方格图 (N≤9),我们将其中的某些方格中填入正整数,而其他的方格中则放入数字 00。如下图所示(见样例):

A
 0  0  0  0  0  0  0  0
 0  0 13  0  0  6  0  0
 0  0  0  0  7  0  0  0
 0  0  0 14  0  0  0  0
 0 21  0  0  0  4  0  0
 0  0 15  0  0  0  0  0
 0 14  0  0  0  0  0  0
 0  0  0  0  0  0  0  0
                         B

某人从图的左上角的 A 点出发,可以向下行走,也可以向右走,直到到达右下角的 B 点。在走过的路上,他可以取走方格中的数(取走后的方格中将变为数字 0)。
此人从 A 点到 B 点共走两次,试找出 2 条这样的路径,使得取得的数之和为最大。

输入格式

输入的第一行为一个整数 N*(表示N×*N 的方格图),接下来的每行有三个整数,前两个表示位置,第三个数为该位置上所放的数。一行单独的 0 表示输入结束。

输出格式

只需输出一个整数,表示 2 条路径上取得的最大的和。

输入输出样例

输入 #1

8
2 3 13
2 6  6
3 5  7
4 4 14
5 2 21
5 6  4
6 3 15
7 2 14
0 0  0

输出 #1

67

说明/提示

NOIP 2000 提高组第四题

代码

#include<cstdio>
#include<algorithm>
using namespace std;
struct point
{
    int x,y,data;
}p[100];
int n,m,map[11][11],f[11][11][11][11];
int main()
{
    int i,j,k,l;
    scanf("%d",&n);
    while(1)
    {
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        if(!a&&!b&&!c)
            break;
        p[++m].x=a;
        p[m].y=b;
        p[m].data=c;
    }
    for(i=1;i<=m;i++)
        map[p[i].x][p[i].y]=p[i].data;
    for(i=1;i<=n;i++)
        for(j=1;j<=n;j++)
            for(k=1;k<=n;k++)
            {
                l=i+j-k;
                if(l<=0)
                    break;
                f[i][j][k][l]=max(f[i-1][j][k-1][l],max(f[i-1][j][k][l-1],max(f[i][j-1][k-1][l],f[i][j-1][k][l-1])));
                if(i==k&&j==l)
                    f[i][j][k][l]+=map[i][j];
                else
                    f[i][j][k][l]+=map[i][j]+map[k][l];
            }
    printf("%d\n",f[n][n][n][n]);
    return 0;
}

5.P1005 矩阵取数游戏

题目描述

帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的 n×m 的矩阵,矩阵中的每个元素 a i,j 均为非负整数。游戏规则如下:

  1. 每次取数时须从每行各取走一个元素,共 n 个。经过 m 次后取完矩阵内所有元素;
  2. 每次取走的各个元素只能是该元素所在行的行首或行尾;
  3. 每次取数都有一个得分值,为每行取数的得分之和,每行取数的得分 = 被取走的元素值 \times 2i,其中i 表示第i次取数(从 1 开始编号);
  4. 游戏结束总得分为 m 次取数得分之和。

帅帅想请你帮忙写一个程序,对于任意矩阵,可以求出取数后的最大得分。

输入格式

输入文件包括 n+1 行:

第一行为两个用空格隔开的整数 nm

第 2∽n+1 行为 n×m 矩阵,其中每行有 m 个用单个空格隔开的非负整数。

输出格式

输出文件仅包含11行,为一个整数,即输入矩阵取数后的最大得分。

输入输出样例

输入 #1

2 3
1 2 3
3 4 2

输出 #1

82

在这里插入图片描述

代码

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>

using namespace std;

const int MAXN = 85, Mod = 10000; //高精四位压缩大法好 
int n, m;
int ar[MAXN];

struct HP {
    int p[505], len;
    HP() {
        memset(p, 0, sizeof p);
        len = 0;
    } //这是构造函数,用于直接创建一个高精度变量 
    void print() {
        printf("%d", p[len]);  
        for (int i = len - 1; i > 0; i--) {  
            if (p[i] == 0) {
                printf("0000"); 
                continue;
            }
            for (int k = 10; k * p[i] < Mod; k *= 10) 
                printf("0");
            printf("%d", p[i]);
        }
    } //四位压缩的输出 
} f[MAXN][MAXN], base[MAXN], ans;

HP operator + (const HP &a, const HP &b) {
    HP c; c.len = max(a.len, b.len); int x = 0;
    for (int i = 1; i <= c.len; i++) {
        c.p[i] = a.p[i] + b.p[i] + x;
        x = c.p[i] / Mod;
        c.p[i] %= Mod;
    }
    if (x > 0)
        c.p[++c.len] = x;
    return c;
} //高精+高精 

HP operator * (const HP &a, const int &b) {
    HP c; c.len = a.len; int x = 0;
    for (int i = 1; i <= c.len; i++) {
        c.p[i] = a.p[i] * b + x;
        x = c.p[i] / Mod;
        c.p[i] %= Mod;
    }
    while (x > 0)
        c.p[++c.len] = x % Mod, x /= Mod;
    return c;
} //高精*单精 

HP max(const HP &a, const HP &b) {
    if (a.len > b.len)
        return a;
    else if (a.len < b.len)
        return b;
    for (int i = a.len; i > 0; i--)
        if (a.p[i] > b.p[i])
            return a;
        else if (a.p[i] < b.p[i])
            return b;
    return a;
} //比较取最大值 

void BaseTwo() {
    base[0].p[1] = 1, base[0].len = 1;
    for (int i = 1; i <= m + 2; i++){ //这里是m! m! m! 我TM写成n调了n年... 
        base[i] = base[i - 1] * 2;
    }
} //预处理出2的幂 

int main(void) {
    scanf("%d%d", &n, &m);
    BaseTwo();
    while (n--) {
        memset(f, 0, sizeof f);
        for (int i = 1; i <= m; i++)
            scanf("%d", &ar[i]);
        for (int i = 1; i <= m; i++)
            for (int j = m; j >= i; j--) { //因为终值是小区间,DP自然就从大区间开始 
                f[i][j] = max(f[i][j], f[i - 1][j] + base[m - j + i - 1] * ar[i - 1]); 
                f[i][j] = max(f[i][j], f[i][j + 1] + base[m - j + i - 1] * ar[j + 1]);
            } //用结构体重载运算符写起来比较自然 
        HP Max;
        for (int i = 1; i <= m; i++)
            Max = max(Max, f[i][i] + base[m] * ar[i]);
        ans = ans + Max; //记录到总答案中 
    }
    ans.print(); //输出 
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值