简单模拟与链表

[COCI2006-2007#1] Modulo

洛谷题源

题目描述

Given two integers A and B, A modulo B is the remainder when dividing A by B. For example, the numbers 7, 14, 27 and 38 become 1, 2, 0 and 2, modulo 3. Write a program that accepts 10 numbers as input and outputs the number of distinct numbers in the input, if the numbers are considered modulo 42.

输入格式

The input will contain 10 non-negative integers, each smaller than 1000, one per line.

输出格式

Output the number of distinct values when considered modulo 42 on a single line.

思路

有多少个不同的余数,余数就只有0-41这些可能,定义一个42大小的数组,有这个位置的余数就置1,没有就是0不变。最后遍历数组,数一下多少个1就行了。

代码

#include <iostream>
#include <cstring>

using namespace std;
int a[42];
int main()
{
    int sum = 0, x;
    memset(a,0,sizeof(a));
    for(int i=0; i<10; i++){
        cin>>x;
        a[x%42] = 1;
    }
    for(int i=0; i<42; i++){
        if(a[i])
            sum++;
    }
    cout<<sum;
    return 0;
}

The Blocks Problem

洛谷题源

题面翻译

初始时从左到右有 n n n 个木块,编号为 0 … n − 1 0 \ldots n-1 0n1,要求实现下列四种操作:

  • move a onto b : 把 a a a b b b 上方的木块归位,然后把 a a a 放到 b b b 上面。
  • move a over b : 把 a a a 上方的木块归位,然后把 a a a 放在 b b b 所在木块堆的最上方。
  • pile a onto b : 把 b b b 上方的木块归位,然后把 a a a 及以上的木块坨到 b b b 上面。
  • pile a over b : 把 a a a 及以上的木块坨到 b b b 的上面。
  • 一组数据的结束标志为 quit,如果有非法指令(如 a a a b b b 在同一堆),无需处理。

输出:所有操作输入完毕后,从左到右,从下到上输出每个位置的木块编号。

题目描述

PDF

输入格式

输出格式

思路:

可以定义一个vector数组(数组的每一个位置是一个vector向量)
把操作理解为两种:归位和移动。
归位:把a或b上面的所有元素放回原来的位置。
移动:把a和a上面的元素移动到b所在堆的上方

代码

#include <iostream>
#include <vector>

using namespace std;

vector<int>block[25+5];//定义30个堆,每个堆都是一个vector向量
int n;

void init(){//初始化n个堆,分别存入一个恰好等于其堆序号的值
    cin>>n;
    for(int i=0;i<n;i++)
        block[i].push_back(i);
}

void loc(int x, int &p, int &h){//找到x的位置,p:第几个堆,h:所在高度
    for(int i=0;i<n;i++)
        for(int j=0;j<block[i].size();j++)
        {
            if(block[i][j] == x)
            {
                p = i;
                h = j;
            }
        }
}

void goback(int p, int h)
{//把序号为p的堆的h以上的元素归位
    for(int i=h+1;i<block[p].size();i++)
    {
        int k = block[p][i];
        block[k].push_back(k);
    }
    block[p].resize(h+1);//重置堆的大小
}

void moveall(int p, int h, int q)
{//将序号为p的堆的高度为h及以上的所有元素移动到序号q的堆上方
    for(int i = h; i<block[p].size(); i++)
    {
        int k = block[p][i];
        block[q].push_back(k);
    }
    block[p].resize(h);//重置堆的大小
}

void solve()
{
    int a,b;
    string s1,s2;
    while(cin>>s1)
    {
        if(s1 == "quit")
            break;
        cin>>a>>s2>>b;
        int ap = 0, ah=0, bp=0, bh=0;//所在堆号和高度
        loc(a,ap,ah);
        loc(b,bp,bh);
        if(ap == bp)
            continue;
        if(s1=="move")//a归位
            goback(ap,ah);
        if(s2 == "onto")//b归位
            goback(bp,bh);
        moveall(ap,ah,bp);
    }
}

void print()
{
    for(int i=0;i<n;i++)
    {
        cout<<i<<":";
        for(int j=0;j<block[i].size();j++)
            cout<<" "<<block[i][j];
        cout<<endl;
    }
}

int main()
{
    init();
    solve();
    print();
    return 0;
}

[USACO09OCT]The Robot Plow G

洛谷题源

题目描述

Farmer John has purchased a new robotic plow in order to relieve him from the drudgery of plowing field after field after field. It achieves this goal but at a slight disadvantage: the robotic plow can only plow in a perfect rectangle with sides of integer length.

Because FJ’s field has trees and other obstacles, FJ sets up the plow to plow many different rectangles, which might end up overlapping. He’s curious as to just how many squares in his field are actually plowed after he programs the plow with various plow instructions, each of which describes a rectangle by giving its lower left and upper right x,y coordinates.

As usual, the field is partitioned into squares whose sides are parallel to the x and y axes. The field is X squares wide and Y squares high (1 <= X <= 240; 1 <= Y <= 240). Each of the I (1 <= I <= 200) plow instructions comprises four integers: Xll, Yll, Xur, and Yur (1 <= Xll <= Xur; Xll <= Xur <= X; 1 <= Yll <= Yur; Yll <= Yur <= Y) which are the lower left and upper right coordinates of the rectangle to be plowed. The plow will plow all the field’s squares in the range (Xll…Xur, Yll…Yur) which might be one more row and column than would initially be assumed (depending on how you go about your assumptions, of course).

Consider a field that is 6 squares wide and 4 squares high. As FJ issues a pair of plowing instructions (shown), the field gets plowed as shown by ‘*’ and ‘#’ (normally plowed field all looks the same, but ‘#’ shows which were most recently plowed):

......             **....             #####. 
......  (1,1)(2,4) **....  (1,3)(5,4) #####. 
......             **....             **.... 
......             **....             **.... 

A total of 14 squares are plowed.

POINTS: 25

Farmer John为了让自己从无穷无尽的犁田工作中解放出来,于是买了个新机器人帮助他犁田。这个机器人可以完成犁田的任务,可惜有一个小小的缺点:这个犁田机器人一次只能犁一个边的长度是整数的长方形的田地。

因为FJ的田地有树和其它障碍物,所以FJ设定机器人去犁很多不同的长方形。这些长方形允许重叠。他给机器人下了P个指令,每个指令包含一个要犁长方形的地。这片田地由长方形的左下角和右上角坐标决定。他很好奇最后到底有多少个方格的地被犁过了。

一般来说,田地被分割为很多小方格。这些方格的边和x轴或y轴平行。田地的宽度为X个方格,高度为Y个方格 (1 <= X <= 240; 1 <= Y <= 240). FJ执行了I (1 <= I <= 200)个指令,每个指令包含4个整数:Xll, Yll, Xur, Yur (1 <= Xll <= Xur; Xll <= Xur <=X; 1 <= Yll <= Yur; Yll <= Yur <= Y), 分别是要犁的长方形的左下角坐标和右上角坐标。机器人会犁所有的横坐标在Xll…Xur并且纵坐标在Yll…Yur范围内的所有方格的地。可能这个长方形会比你想象的多一行一列(就是说从第Xll列到第Xur列一共有Xur - Xll + 1列而不是Xur - Xll列)。

考虑一个6方格宽4方格高的田地。FJ进行了2个操作(如下),田地就被犁成"*“和”#“了。虽然一般被犁过的地看起来都是一样的。但是标成”#"可以更清晰地看出最近一次被犁的长方形。

一共14个方格的地被犁过了。

输入格式

* Line 1: Three space-separated integers: X, Y, and I

* Lines 2…I+1: Line i+1 contains plowing instruction i which is described by four integers: Xll, Yll, Xur, and Yur

输出格式

* Line 1: A single integer that is the total number of squares plowed

思路:

定义一个二维数组,凡是经过的位置置1,最后数一遍就行了

代码

#include <iostream>
#include <cstring>
#include <bits/stdc++.h>
using namespace std;
int a[240+5][240+5];
void ex(int x, int y, int s, int t){
    for(int i=x;i<=s;i++)
            for(int j = y; j<=t;j++)
                a[i][j] = 1;
}
int main()
{
    int m,n,c,count=0;
    int x1,y1,x2,y2;
    //memset();函数来自cstring,对数组进行初始化
    //对静态数组可以直接sizeof(a);要是动态数组要用数组元素个数n*sizeof(数组元素类型int)
    memset(a,0,sizeof(a));
    cin>>m>>n>>c;

    for(int i=0; i<c;i++){
        cin>>x1>>y1>>x2>>y2;
        ex(x1,y1,x2,y2);
    }

    for(int i = 1; i<=m; i++)
        for(int j=1;j<=n;j++)
            if(a[i][j])
                count++;
    cout<<count;
    return 0;
}

破损的键盘 Broken Keyboard (a.k.a. Beiju Text)


题面翻译

你在输入文章的时候,键盘上的Home键和End键出了问题,会不定时的按下。你却不知道此问题,而是专心致志地打稿子,甚至显示器都没开。当你打开显示器之后,展现你面前的数一段悲剧文本。你的任务是在显示器打开前计算出这段悲剧的文本。
给你一段按键的文本,其中’[‘表示Home键,’]'表示End键,输入结束标志是文件结束符(EOF)。

输出一行,即这段悲剧文本。
翻译贡献者UID:71371

题目描述

PDF

输入格式

输出格式

样例

样例输入

This_is_a_[Beiju]_text
[[]][][]Happy_Birthday_to_Tsinghua_University

样例输出

BeijuThis_is_a__text
Happy_Birthday_to_Tsinghua_University

思路:

想要模拟这个过程,显然需要频繁地在首尾插入,所以采用链表。
可以利用迭代器来指示要操作的位置:

list<char>::iterator it = text.begin();
it = text.begin();//模拟home
it = text.end();//模拟end
it = text.insert(it,s[i]);//在it指示的位置插入s[i],返回的it指示的是插入的元素的位置,此时如果再进行一次插入就是在这个元素前面插入(把刚刚插入的元素往后挤),所以如果想达到题目的要求,必须进行i++操作

代码

#include <iostream>
#include <list>

using namespace std;

list<char> text;

void solve(string s){
    int len = s.length();
    list<char>::iterator it = text.begin();
    for(int i=0;i<len;i++)
    {
        if(s[i]=='[')
            it=text.begin();
        else if(s[i]==']')
            it = text.end();
        else
        {
            it = text.insert(it,s[i]);
            it++;
        }
    }
    for(it = text.begin();it!=text.end();it++)
        cout<<*it;
    text.clear();
    cout<<endl;
}


int main()
{
    string s;
    while(cin>>s)
        solve(s);
    return 0;
}

最长连号

洛谷题源

题目描述

输入长度为 n n n 的一个正整数序列,要求输出序列中最长连号的长度。

连号指在序列中,从小到大的连续自然数。

输入格式

第一行,一个整数 n n n

第二行, n n n 个整数 a i a_i ai,之间用空格隔开。

输出格式

一个数,最长连号的个数。

样例 #1

样例输入 #1

10
1 5 6 2 3 4 5 6 8 9

样例输出 #1

5

提示

数据规模与约定

对于 100 % 100\% 100% 的数据,保证 1 ≤ n ≤ 1 0 4 1 \leq n \leq 10^4 1n104 1 ≤ a i ≤ 1 0 9 1 \leq a_i \leq 10^9 1ai109

思路:

遍历数组,用一个计数器记录连续多少个数满足条件了,再用一个最大值寄存器记录目前最大的连续个数

代码

#include <iostream>

using namespace std;

int a[10000+5];
int main()
{
    int n, cnt = 1, maxl = 1;
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>a[i];
    }
    for(int i = 0; i<n; i++){
        if(a[i+1] == a[i]+1){
            cnt++;
            if(maxl<cnt)
                maxl = cnt;
        }
        else
            cnt = 1;
    }
    cout<<maxl;
    return 0;
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值