NOIP 2008 PJT4~NOIP 2010 PJT4

1.2099: 立体图(NOIP 2008 PJT4)

题目描述

小渊是个聪明的孩子,他经常会给周围的小朋友们将写自己认为有趣的内容。最近,他准备给小朋友们讲解立体图,请你帮他画出立体图。 小渊有一块面积为m×n�×�的矩形区域,上面有m×n�×�个边长为11的格子,每个格子上堆了一些同样大小的积木(积木的长宽高都是11),小渊想请你打印出这些格子的立体图。我们定义每个积木为如下格式,并且不会做任何翻转旋转,只会严格以这一种形式摆放:
 


每个顶点用11个加号’++’表示,长用33个”−−”表示,宽用11个”/”,高用两个”|”表示。字符’++’,”−−”,”/”,”|”的ASCII�����码分别为4343,4545,4747,124124。字符’.’(ASCII�����码4646)需要作为背景输出,即立体图里的空白部分需要用’.’来代替。立体图的画法如下面的规则:
若两块积木左右相邻,图示为:
 


若两块积木上下相邻,图示为:
 


若两块积木前后相邻,图示为:
 


立体图中,定义位于第(m,1(�,1)的格子(即第m�行第11列的格子)上面自底向上的第一块积木(即最下面的一块积木)的左下角顶点为整张图最左下角的点。

输入

第一行有用空格隔开的22个整数m�和n�,表示有m×n�×�个格子(1≤m,n≤50)(1≤�,�≤50)。
接下来的m�行,是一个m×n�×�的矩阵,每行有n�个用空格隔开的整数,其中第i�行第j�列上的整数表示第i�行第j�列的个子上摞有多少个积木(1≤1≤每个格子上的积木数≤100≤100)。

输出

输出包含题目要求的立体图,是一个K�行L�列的字符串矩阵,其中K�和L�表示最少需要K�行L�列才能按规定输出立体图。

样例输入 复制

3 4
2 2 1 2
2 2 1 1
3 2 1 2

样例输出 复制

......+---+---+...+---+
..+---+  /   /|../   /|
./   /|-+---+ |.+---+ |
+---+ |/   /| +-|   | +
|   | +---+ |/+---+ |/|
|   |/   /| +/   /|-+ |
+---+---+ |/+---+ |/| +
|   |   | +-|   | + |/.
|   |   |/  |   |/| +..
+---+---+---+---+ |/...
|   |   |   |   | +....
|   |   |   |   |/.....
+---+---+---+---+......
题目信息
  • 提交: 30正确: 22
  • 时间限制: 1 秒
  • 内存限制: 128 MB
  • 难度等级: 6 级
  • 创建人: lx
  • 提交统计
推荐题目
  • 更多同类题目

时间限制: 1 秒  内存限制: 128 MB  提交: 30  AC: 22    [提交][状态]

#include <iostream>
#include <algorithm>
    
using namespace std;
    
const int N = 500, M = 60;
    
int n, m;
char box[6][8] = {
    "..+---+",
    "./   /|",
    "+---+ |",
    "|   | +",
    "|   |/.",
    "+---+.."
};
    
char g[N][N];
int h[M][M];
    
int main()
{
    cin >> n >> m;
    for (int i = 0; i < n; i ++ )
        for (int j = 0; j < m; j ++ )
            cin >> h[i][j];
    
    // i = 1, j = n - 1, k = 0: 499, 0
    // i = 1, j = n - 2, k = 0: 497, 2
    // i = 1, j = n - 1, k = 1: 499, 4
    // ...
    
    // i = 2, j = n - 1, k = 0: 496, 0
    // i = 2, j = n - 2, k = 0: 494, 2
    // ...
    
    // 499 - (i - 1) * 3 - j * 2
    // j * 2 + k * 4
    
    for (int i = 0; i < N; i ++ )
        for (int j = 0; j < N; j ++ )
            g[i][j] = '.';
    
    for (int i = 1; i <= 100; i ++ )
        for (int j = 0; j < n; j ++ )
            for (int k = 0; k < m; k ++ )
                if (h[j][k] >= i)
                {
                    int x = 499 - (i - 1) * 3 - (n - 1 - j) * 2;
                    int y = (n - 1 - j) * 2 + k * 4;
    
                    for (int a = 0; a < 6; a ++ )
                        for (int b = 0; b < 7; b ++ )
                            if (box[a][b] != '.')
                                g[x - 5 + a][y + b] = box[a][b];
                }
    
    int x = 0;
    for (int i = 0; ; i ++ )
    {
        bool flag = false;
        for (int j = 0; j < N; j ++ )
            if (g[i][j] != '.')
            {
                flag = true;
                break;
            }
    
        x = i;
        if (flag) break;
    }
    
    int y = N - 1;
    for (int i = N - 1; ; i -- )
    {
        bool flag = false;
        for (int j = 0; j < N; j ++ )
            if (g[j][i] != '.')
            {
                flag = true;
                break;
            }
    
        y = i;
        if (flag) break;
    }
    
    for (int i = x; i < N; i ++ )
    {
        for (int j = 0; j <= y; j ++ )
            cout << g[i][j];
        cout << endl;
    }
    
    return 0;
}

2.2103: 道路游戏(NOIP 2009 PJT4)

题目描述

小新正在玩一个简单的电脑游戏。 游戏中有一条环形马路,马路上有 n� 个机器人工厂,两个相邻机器人工厂之间由一小段马路连接。小新以某个机器人工厂为起点,按顺时针顺序依次将这 n� 个机器人工厂编号为 1∼n1∼�,因为马路是环形的,所以第 n� 个机器人工厂和第 11 个机器人工厂是由一段马路连接在一起的。小新将连接机器人工厂的这 n� 段马路也编号为 1∼n1∼�,并规定第 i� 段马路连接第 i� 个机器人工厂和第 i+1�+1 个机器人工厂(1≤i≤n−11≤�≤�−1),第 n� 段马路连接第 n� 个机器人工厂和第 11 个机器人工厂。
游戏过程中,每个单位时间内,每段马路上都会出现一些金币,金币的数量会随着时间发生变化,即不同单位时间内同一段马路上出现的金币数量可能是不同的。小新需要机器人的帮助才能收集到马路上的金币。所需的机器人必须在机器人工厂用一些金币来购买,机器人一旦被购买,便会沿着环形马路按顺时针方向一直行走,在每个单位时间内行走一次,即从当前所在的机器人工厂到达相邻的下一个机器人工厂,并将经过的马路上的所有金币收集给小新,例如,小新在 i�(1≤i≤n1≤�≤�)号机器人工厂购买了一个机器人,这个机器人会从 i� 号机器人工厂开始,顺时针在马路上行走,第一次行走会经过 i� 号马路,到达 i+1�+1 号机器人工厂(如果 i=n�=�,机器人会到达第 11 个机器人工厂),并将 i� 号马路上的所有金币收集给小新。游戏中,环形马路上不能同时存在 22 个或者 22 个以上的机器人,并且每个机器人最多能够在环形马路上行走 p� 次。小新购买机器人的同时,需要给这个机器人设定行走次数,行走次数可以为 1 p1 � 之间的任意整数。当马路上的机器人行走完规定的次数之后会自动消失,小新必须立刻在任意一个机器人工厂中购买一个新的机器人,并给新的机器人设定新的行走次数。
以下是游戏的一些补充说明:
1. 游戏从小新第一次购买机器人开始计时。
2. 购买机器人和设定机器人的行走次数是瞬间完成的,不需要花费时间。
3. 购买机器人和机器人行走是两个独立的过程,机器人行走时不能购买机器人,购买完机器人并且设定机器人行走次数之后机器人才能行走。
4. 在同一个机器人工厂购买机器人的花费是相同的,但是在不同机器人工厂购买机器人的花费不一定相同。
5. 购买机器人花费的金币,在游戏结束时再从小新收集的金币中扣除,所以在游戏过程中小新不用担心因金币不足,无法购买机器人而导致游戏无法进行。也因为如此,游戏结束后,收集的金币数量可能为负。
现在已知每段马路上每个单位时间内出现的金币数量和在每个机器人工厂购买机器人需要的花费,请你告诉小新,经过 m� 个单位时间后,扣除购买机器人的花费,小新最多能收集到多少金币。

输入

第一行 33 个正整数 n,m,p�,�,�,意义如题目所述。
接下来的 n� 行,每行有 m� 个正整数,每两个整数之间用一个空格隔开,其中第 i� 行描。
述了 i� 号马路上每个单位时间内出现的金币数量(1≤1≤ 金币数量 ≤100≤100),即第 i� 行的第 j�(1≤j≤m1≤�≤�)个数表示第 j� 个单位时间内 i� 号马路上出现的金币数量。
最后一行,有 n� 个整数,每两个整数之间用一个空格隔开,其中第 i� 个数表示在 i� 号机器人工厂购买机器人需要花费的金币数量(1≤1≤ 金币数量 ≤100≤100)。

输出

共一行,包含 11 个整数,表示在 m� 个单位时间内,扣除购买机器人花费的金币之后,小新最多能收集到多少金币。

样例输入 复制

2 3 2 
1 2 3 
2 3 4 
1 2

样例输出 复制

5

提示

对于 40%40% 的数据,2≤n≤402≤�≤40,1≤m≤401≤�≤40。
对于 90%90% 的数据,2≤n≤2002≤�≤200,1≤m≤2001≤�≤200。
对于 100%100% 的数据,2≤n≤10002≤�≤1000,1≤m≤10001≤�≤1000,1≤p≤m1≤�≤�。

题目信息
  • 提交: 28正确: 24
  • 时间限制: 1 秒
  • 内存限制: 128 MB
  • 难度等级: 6 级
  • 创建人: lx
  • 提交统计
推荐题目
  • 更多同类题目

时间限制: 1 秒  内存限制: 128 MB  提交: 28  AC: 24    [提交][状态]

#include <bits/stdc++.h>
using namespace std;
int f[1010],a[1010][1010],cost[1010],n,m,p;
#define inf 0x3f3f3f3f
int main(){
    scanf("%d%d%d",&n,&m,&p);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            scanf("%d",&a[i][j]);
        }
    }
    for(int i=1;i<=n;i++)scanf("%d",&cost[i]);
    for(int i=1;i<=n;i++)f[i]=-inf;
    f[0]=0;
    for(int i=1;i<=m;i++){
        for(int j=1;j<=n;j++){
            int sum=0,t=j-1;
            if(!t)t=n;
            sum=a[t][i];
            for(int k=1;k<=p;k++){
                if(i-k<0)break;
                f[i]=max(f[i],f[i-k]+sum-cost[t]);
                t--;if(!t)t=n;
                sum+=a[t][i-k];
            }
        }
    }
    printf("%d\n",f[m]);
}

2.2121: 表达式的值(NOIP 2011 PJT4)

题目描述

对于1 位二进制变量定义两种运算:
 


运算的优先级是:
1. 先计算括号内的,再计算括号外的。
2. “× ”运算优先于“⊕”运算,即计算表达式时,先计算× 运算,再计算⊕运算。例如:计算表达式A⊕B × C时,先计算 B × C,其结果再与 A 做⊕运算。
现给定一个未完成的表达式,例如\_+(\_\*\_),请你在横线处填入数字00或者11 ,请问有多少种填法可以使得表达式的值为00。

输入

共 2 行。 第1 行为一个整数 L�,表示给定的表达式中除去横线外的运算符和括号的个数。 第2 行为一个字符串包含 L� 个字符,其中只包含’(’、’)’、’+’、’*’这44 种字符,其中’(’、’)’是左右括号,’+’、’*’分别表示前面定义的运算符“⊕”和“×”。这行字符按顺序给出了给定表达式中除去变量外的运算符和括号。

输出

共1 行。包含一个整数,即所有的方案数。注意:这个数可能会很大,请输出方案数对1000710007取模后的结果。

样例输入 复制

4
+(*)

样例输出 复制

3

提示

【输入输出样例说明】
给定的表达式包括横线字符之后为:\_+(\_\*\_)
在横线位置填入(0 、0 、0) 、(0 、1 、0) 、(0 、0 、1) 时,表达式的值均为0 ,所以共有3种填法。
【数据范围】
对于 20%20% 的数据有 0≤L≤100≤�≤10。
对于 50%50% 的数据有 0≤L≤1,0000≤�≤1,000。
对于 70%70% 的数据有 0≤L≤10,0000≤�≤10,000 。
对于 100%100%的数据有 0≤L≤100,0000≤�≤100,000。
对于50%50% 的数据输入表达式中不含括号。

题目信息
  • 提交: 29正确: 21
  • 时间限制: 1 秒
  • 内存限制: 128 MB
  • 难度等级: 6 级
  • 创建人: lx
  • 提交统计
推荐题目
  • 更多同类题目

时间限制: 1 秒  内存限制: 128 MB  提交: 29  AC: 21    [提交][状态]

#include<cstdio>
#include<cmath>
#include<cstring>
#include<cctype>
#include<algorithm>
using namespace std;
const int maxn=150010,mod=10007;
char s[maxn*2],t[maxn*2],now[maxn*2],c;
int lenn,lent,len,num,n;
int f[maxn][2];
void jrz()
{
    while(now[lenn]=='+'||now[lenn]=='*')t[++lent]=now[lenn--];
    now[++lenn]='+';
}
void crz()
{
    while(now[lenn]=='*')t[++lent]=now[lenn--];
    now[++lenn]='*';
}
void kcz()
{
    while(now[lenn]!='(')t[++lent]=now[lenn--];
    lenn--;
}
void pluss()
{
    f[num][1]=(f[num][0]*f[num+1][1]+f[num][1]*f[num+1][0]+f[num][1]*f[num+1][1])%mod;
    f[num][0]=(f[num][0]*f[num+1][0])%mod;
}
void cheng()
{
    f[num][0]=(f[num][0]*f[num+1][1]+f[num][1]*f[num+1][0]+f[num][0]*f[num+1][0])%mod;
    f[num][1]=(f[num][1]*f[num+1][1])%mod;
}
void change()
{
    now[0]='(';lenn=0;lent=-1;
    for(int i=0;i<=len;i++)
     {//printf("%d",i);
     //for(int j=0;j<=lenn;j++)printf("%c",now[j]);
     //printf("   lenn=%d\n",lenn);
         if(s[i]=='_')t[++lent]='_';
         if(s[i]=='+')jrz();
         if(s[i]=='*')crz();
         if(s[i]=='(')now[++lenn]='(';
         if(s[i]==')')kcz();
     }
    kcz();//printf("lenn=%d",lenn);printf("[t]\n\n%s\n\n",t);
}
void work()
{
    num=0;
    for(int i=0;i<=lent;i++)
     {
         if(t[i]=='_')
          {
              num++;
              f[num][0]=1;f[num][1]=1;
          }
         if(t[i]=='+')num--,pluss();//printf("f[%d][0]=%d,f[%d][1]=%d\n",num,f[num][0],num,f[num][1]);
         if(t[i]=='*')num--,cheng();//printf("f[%d][0]=%d,f[%d][1]=%d\n",num,f[num][0],num,f[num][1]);
     }
}
int main()
{
//    freopen("exp.in","r",stdin);
//    freopen("exp.out","w",stdout);
    scanf("%d",&n);
    c=getchar();c=getchar();
    len=-1;
    if(c!='(')s[0]='_',len=0;
    s[++len]=c;
    for(int i=2;i<=n;i++)
     {
         c=getchar();
         if(c!='('&&s[len]!=')')s[++len]='_';
         s[++len]=c;
     }
    if(c!=')')s[++len]='_';
//    printf("\n\n%s\n\n",s);
    change();
    work();
    printf("%d",f[1][0]);
    return 0;
}

  • 27
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值