OJ刷题

主要是准备北邮的复试...

OJ的输入与输出

这个得总结一下,我刚看到的题目描述很奇怪,输入了半天也不对,后来才发现这个OJ对输入输出是有套路的,先总结一下

  • 一个case输入,一个case输出

这种直接使用scanf与printf即可

  • 输入:多个case输入直到文件结束,输出格式:一行一个输出结果

这里要这样写:

    while (scanf("%d %d",&i,&j)!=EOF)
    {
        /* code */
        printf("%d\n",(i+j));

    }
  • 先输入case个数,然后依次输入每个case,输出格式:一行一个输出
    int cishu;
    scanf("%d",&cishu);
    while (cishu--)
    {
        /* code */
        scanf("%d %d",&i,&j);
        printf("%d\n",(i+j));
     }
  • 每行输入一个case,当case满足某种情况时退出,输出格式,一行一个输出结果
while(1){
   if(/* code */) break;
    // todo
}

字符的输入与输出

输入一个字符:getchar()
输出一个字符:putchar()

但是这两个函数有点坑...

#include<stdio.h>


int main(){
    int n;
    char a,b;
    scanf("%d",&n);
    //getchar();
    while (n--)
    {
         scanf("%c%c",&a,&b);
      //   getchar();
         printf("%c%c",a,b);
         
    }
    
   
    return 0;
}

把注释解开,运行一下就知道了...

day01

二哥种苹果

https://acm.sjtu.edu.cn/OnlineJudge/problem/1001

package com.four1er.Demo.Demo01Day;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.Buffer;
import java.util.Scanner;

/*
题目描述
二哥平日喜欢自己种一些东西,并以此为写程序和看电影之外的最大爱好。
最近,二哥种的一棵苹果树到了采摘的时候,但是由于二哥身高的限制,有些苹果太高摘不到。于是二哥借来了一个凳子,踩在上面可以摘到更多的苹果。
二哥是一个懒于行动的人,他想在摘苹果之前知道自己能摘到多少苹果,
如果实在太少(苹果树很茂盛,主要是由于身高原因),他宁可坐在树下等苹果自己掉下来砸到头上。

输入格式
输入共有两行。

第1行有3个整数,分别表示二哥的身高、凳子的高度和苹果的个数n。

第2行有n个整数,分别表示每个苹果的高度。

输出格式
输出一个整数m,表示二哥最多能摘到的苹果的个数为m。

说明
对于全部数据:高度为1000以下的正整数,苹果的个数
1≤n≤1000
 */
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        String s = br.readLine();
        String[] strings =s.trim().split(" ");
        int broHgih=Integer.parseInt(strings[0]);
        int chairHgih=Integer.parseInt(strings[1]);
        int appleNum=Integer.parseInt(strings[2]);
        strings=br.readLine().trim().split(" ");
        int[] appleHigh=new int[appleNum];
        int account=0;
        for(int i=0; i<appleNum;i++){
            appleHigh[i]=Integer.parseInt(strings[i]);
            if(appleHigh[i]<=(broHgih+chairHgih)){
                account++;
            }
        }
        System.out.println(account);
    }
}

这题还是收获了很多的,主要在于输入输出这一块,以后遇到再总结

BufferedReader与InputStreamReader

 // 创建一个BufferedReader对象
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        // 读取字符串
        String line = br.readLine();

这两个用来读字符输入真的很好,效率比Scanner要高。

然后用readline接收数据流。

对于想要得到的数据,String[] strings =s.trim().split(" ");

然后根据类型,用Integer自带的static方法parseInt(string[i])来接收,这样虽然慢了一点,不过效率还是蛮高的。

二哥种花生

这题.... 说实话我写的时候就知道时间复杂度觉得爆炸了,但是没办法,硬着头皮写完了,其实out应该是没问题的...

但是这题目的应该是前缀和法,不过我压根就没听过??🤣🤣

就60分...
先把自己的代码贴出来,回头再思考一下...

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String readLine = br.readLine();
        String[] strings = readLine.trim().split(" ");
        int L = Integer.parseInt(strings[0]);
        int W = Integer.parseInt(strings[1]);
        int[][] ints = new int[L][W];
        for (int i = 0; i < L; i++) {
            strings = br.readLine().trim().split(" ");
            for (int j = 0; j < W; j++) {
                ints[i][j] = Integer.parseInt(strings[j]);
            }
        }
        strings = br.readLine().trim().split(" ");
        int a = Integer.parseInt(strings[0]);
        int b = Integer.parseInt(strings[1]);

        int max = 0;
        for (int x = 0; x <= L - a; x++) {
            for (int u = 0; u <= W - b; u++) {
                int account = 0;
                for (int i = 0; i < a; i++) {
                    for (int j = 0; j < b; j++) {
                        account += ints[i + x][j + u];
                    }
                }
                if (max < account) {
                    max = account;
                }
            }
        }
        System.out.println(max);
    }
}

不行不行,既然遇到了不会的点还是搞清楚吧,遇到一个解决一个,剩下的两道题先不写了,容我去看看什么叫前缀和...

大概懂了,就是用变求和为求差,避免重复的计算
我妈催我洗澡了,直接把别人的搬过来吧

https://my.oschina.net/xueyang/blog/208428

#include<iostream>


using namespace std;

int main()
{
	int L(0), W(0), t(0);
	cin >> L >> W; //输入花生地的长和宽
	//定义数组
	int **store = new int*[L];
	for (int i = 0; i < L; ++i)	 store[i] = new int[W];
	for (int i = 0; i < L; ++i){
		for (int j = 0; j < W; ++j){
			cin >> t;
			if (j>0&&i>0)store[i][j] = store[i-1][j] + t + store[i][j-1] - store[i-1][j-1];
			else if (j>0 && i == 0)store[i][j] = t + store[i][j-1];
			else if (i > 0 && j == 0)store[i][j] = t + store[i - 1][j];
			else store[i][j] = t;
		}
	}
	int l, w, result(0), temp(0);
	cin >> l >> w;//获得目标区块的大小
	//遍历计算
	for (int i = l - 1; i < L; ++i){
		for (int j = w - 1; j < W; ++j){
			if(i == l- 1 && j == w - 1)temp = store[i][j];
			else if (i == l - 1 && j != w - 1)temp = store[i][j] - store[i][j - w];
			else if (i != l - 1 && j == w - 1)temp = store[i][j] - store[i - l][j];
			else temp = store[i][j] - store[i - l][j] - store[i][j-w] + store[i-l][j-w];
			if (temp >= result)result = temp;
		}
	}
	cout << result;//输出结果
	//释放内存!
	for (int i = 0; i < L; ++i)
		delete[] store[i];
	delete[] store;
	return 0;
}

day02

北邮19网研

Problem A.牙膏问题

题目描述
4只牙膏比较价格,返回最便宜的牙膏
输入:
第一行输入T,表示数据的组数
第二行输入a b c d 表示4只牙膏的价格
输出
返回最低价格

#include <iostream>
#include <algorithm>

using namespace std;

int main() {
    int zushu;
    cin >> zushu;
	int a, b, c, d;
	int arr[4] = {};
	int* out = new int[zushu];
	for (int i = 0; i < zushu; i++)
	{
		cin >> a >> b >> c >> d;
		arr[0] = a;
		arr[1] = b;
		arr[2] = c;
		arr[3] = d;
		sort(arr, arr + 4);
		out[i]=arr[0];
	}
	for (int i = 0; i < zushu; i++)
	{
		cout << out[i]<<endl;
	}
}

Problem B.闰年问题

题目描述
统计连个年份间能被4整除且不能被100整除的普通闰年和能被400整除的世纪闰年的年数

输入:
第一行输入T,表示数据的组数
之后输入T组数据,每组输入x y代表始末年份(y<x)
输出
返回x到y年 ∈[x,y] 内闰年数目

#include<iostream>
#include<algorithm>

using namespace std;

int main() {
	int zushu;

	cin >>zushu;
	int* out1 = new int[zushu];
	int* out2 = new int[zushu];
	for (int i = 0; i < zushu; i++)
	{
		out1[i] = 0;
		out2[i] = 0;
	}
	for (int i = 0; i < zushu; i++)
	{
		int a, b;
		cin >> a >> b;
		for (int x = a; x <= b; x++)
		{
			if ((x % 4 == 0) && (x % 100 != 0)) {
				out1[i]++;
			}
			if (x % 400 == 0) {
				out2[i]++;
			}
		}
	}
	for (int i = 0; i < zushu; i++)
	{
		cout << out1[i] <<" "<<out2[i] << endl;
	}


	return 0;
}

day03

判断奇偶数

这题思路是easy中的easy不过困扰我的点主要是数据的输入

总结一下这题中学到的输入:输入一行数字,以空格分割,存储在一个数组中:

这是本题最大的收获!

#include<iostream>

using namespace std;

#define YES 1
#define NO 0

int main(){
	
	int n;
	cin>>n;
	int* arr=(int*)malloc(4*n);
	int i=0;
    char c=' ';
    while (i<n)
    {
        c=getchar();
        ungetc(c,stdin);
        cin>>arr[i];
        i++;
    }
    int odd=0;
    int even=0;
    for (int i = 0; i < n; i++)
    {
        if(arr[i]%2==0){
            odd+=1;
        }else{
            even+=1;
        }
    }
    if(odd>even){
        cout<<"NO";
    }else{
        cout<<"YES";
    }
    
	return 0;	
}

最小数

送分题...

#include <iostream>

using namespace std;

int main()
{
    int n = 0;
    cin >> n;
    int x = 0, y = 0;
    int min_x = 0, min_y = 0;
    //假定第一组数据最小
    cin >> min_x >> min_y;
    n -= 1;
    while (n--)
    {
        cin >> x >> y;
        if (x <= min_x)
        {
            min_x = x;
            if (y <= min_y)
            {
                min_y = y;
            }
        }
    }
    cout << min_x << " " << min_y << endl;

    return 0;
}

day04

cc反转

这题我感觉不难但是有点绕。。。

#include <iostream>

using namespace std;

int main()
{
    // 先用数组将其存储起来;
    int arr[5][5] = {0};
    for (int i = 0; i < 5; i++)
    {
        cin >> arr[i][0] >> arr[i][1] >> arr[i][2] >> arr[i][3] >> arr[i][4];
    }
    //op_code表示操作类型;
    int op_code1 = 0, op_code2 = 0;
    // arr_x arr_y 表示坐标轴;
    int arr_x = 0, arr_y = 0;
    cin >> op_code1 >> op_code2 >> arr_x >> arr_y;
    int opcode=op_code1*10+op_code2;
    arr_x-=1;
    arr_y-=1;
    int temp_12=0,temp_13_1=0,temp_13_2=0,temp_22=0,temp_23_1=0,temp_23_2=0;
    switch (opcode)
    {
    case 12:
        // 90度,顺时针,翻转4个数
        temp_12=arr[arr_x][arr_y+1];
        arr[arr_x][arr_y+1]=arr[arr_x][arr_y];
        arr[arr_x][arr_y]=arr[arr_x+1][arr_y];
        arr[arr_x+1][arr_y]=arr[arr_x+1][arr_y+1];
        arr[arr_x+1][arr_y+1]=temp_12;
        break;
    case 13:
        temp_13_1=arr[arr_x][arr_y+2];
        temp_13_2=arr[arr_x][arr_y+1];
        arr[arr_x][arr_y+2]=arr[arr_x][arr_y];
        arr[arr_x][arr_y+1]=arr[arr_x+1][arr_y];
        arr[arr_x][arr_y]=arr[arr_x+2][arr_y];
        arr[arr_x+1][arr_y]=arr[arr_x+2][arr_y+1];
        arr[arr_x+2][arr_y]=arr[arr_x+2][arr_y+2];
        arr[arr_x+2][arr_y+1]=arr[arr_x+1][arr_y+2];
        //arr[arr_x+2][arr_y+2]=arr[arr_x][arr_y+2];
        arr[arr_x+2][arr_y+2]=temp_13_1;
        arr[arr_x+1][arr_y+2]=temp_13_2;
        break;

    case 22:
        temp_22=arr[arr_x+1][arr_y];
        arr[arr_x+1][arr_y]=arr[arr_x][arr_y];
        arr[arr_x][arr_y]=arr[arr_x][arr_y+1];
        arr[arr_x][arr_y+1]=arr[arr_x+1][arr_y+1];
        arr[arr_x+1][arr_y+1]=temp_22;
        break;

    case 23:
        temp_23_1=arr[arr_x+2][arr_y];
        temp_23_2=arr[arr_x+1][arr_y];
        arr[arr_x+2][arr_y]=arr[arr_x][arr_y];
        arr[arr_x+1][arr_y]=arr[arr_x][arr_y+1];
        arr[arr_x][arr_y]=arr[arr_x][arr_y+2];
        arr[arr_x][arr_y+1]=arr[arr_x+1][arr_y+2];
        arr[arr_x][arr_y+2]=arr[arr_x+2][arr_y+2];
        arr[arr_x+1][arr_y+2]=arr[arr_x+2][arr_y+1];
        // arr[arr_x+2][arr_y+1]=arr[arr_x][arr_y+2];
        arr[arr_x+2][arr_y+2]=temp_23_1;
        arr[arr_x+2][arr_y+1]=temp_23_2;
        break;
    }
      for (int i = 0; i < 5; i++)
    {
        cout<< arr[i][0]<<" " << arr[i][1] <<" "<< arr[i][2] <<" "<< arr[i][3] <<" "<< arr[i][4]<<endl;
    }
    return 0;
}

复数集合

这是一道收获很大的题目,虽然收获了很多,但是也清晰的认识到了自己还有很多很多不足。
值得放出题目链接,有时间再回顾回顾复数集合

#include <iostream>
#include <vector>
#include <string>
using namespace std;

class FuShu
{
public:
    int x;
    int y;
    int get_mozhi();
    FuShu();
    FuShu(int x, int y);
};

FuShu::FuShu(int x, int y)
{
    this->x = x;
    this->y = y;
}

int FuShu::get_mozhi()
{
    return x ^ 2 + y ^ 2;
}

FuShu select_max(vector<FuShu> &vec_fushu, vector<string> &vec_str)
{

    vector<FuShu>::iterator v = vec_fushu.begin();
    FuShu fushu = *vec_fushu.begin();
    //int temp=0;
    while (v != vec_fushu.end())
    {
        //temp=fuhsu.get_mozhi();
        if (fushu.get_mozhi() <= (*v).get_mozhi())
        {
            fushu = *v;
        }
        v++;
    }

    //得到最大的复数,然后删除。
    vec_fushu.erase(v);
    return fushu;
}

//1、Pop 表示读出集合中复数模值最大的那个复数,如集合为空 输出  empty
void func_pop(vector<FuShu> &vec_fushu, vector<string> &vec_str)
{
    if (vec_fushu.size() == 0)
    {
        vec_str.push_back("empty");
    }
    //不为空就输出最大的那个复数并且从集合中删除那个复数,
    //再输出集合的大小SIZE;
    else
    {
        FuShu max_fushu = select_max(vec_fushu, vec_str);
        int max_x = max_fushu.x;
        int max_y = max_fushu.y;
        string str_fushu = to_string(max_x) + "+i" + to_string(max_y);
        vec_str.push_back(str_fushu);
        int size = vec_fushu.size();
        string s_temp = "SIZE = " + to_string(size);
        vec_str.push_back(s_temp);
    }
}

int func_insert(int x, int y, vector<FuShu> &vec_fushu, vector<string> &vec_str)
{
    FuShu *insert_fushu = new FuShu(x, y);
    vec_fushu.push_back(*insert_fushu);
    return vec_fushu.size();
}

int main()
{
    vector<FuShu> vec_fushu;
    vector<string> vec_str;
    int n;
    cin >> n;
    char c = getchar();
    char cmd[10]={0};
    string str_option;
    string temp;
    string pop = "Pop";
    string insert = "Ins";
    //std::getline(cin,option);
    while (n--)
    {
        scanf("%s",cmd);
        str_option=cmd;

        temp = str_option.substr(0, 3);
        if (!temp.compare(pop))
        {
            func_pop(vec_fushu, vec_str);
        }
        else if (!temp.compare(insert))
        {
            //分割字符串获得x y
            int x = 0, y = 0;
             scanf("%d+i%d", &x, &y);
            int length = func_insert(x, y, vec_fushu, vec_str);
            string s_temp = "SIZE = " + to_string(length);
            vec_str.push_back(s_temp);
        }
    }
    vector<string>::iterator v = vec_str.begin();
    while (v != vec_str.end())
    {
        cout << *v << endl;
        v++;
    }

    return 0;
}

上面是我的代码,写的奇丑无比,而且对C++ STL的很多特性都没有掌握清楚。

再对比一下别人的代码,同样用的vector容器,别人写的就赏心悦目。诶,菜鸡留下了羡慕的眼泪
特别是在插入之后的sort(complex_vector.begin(), complex_vector.end(), comp);这一段,我想了好久好久,一直困惑于vector容器怎么实现大小排序,如今一看,拍案叫绝...主要还是见的少了...

#include<iostream>
#include<algorithm>
#include<vector>
#include<string>
using namespace std;

//复数的结构体
struct Complex {
	int a;//实数
	int b;//虚数
	//构造函数
	Complex(int x,int y):a(x),b(y){}

};

//从小到大排序
bool comp(Complex x, Complex y) {
	if (x.a*x.a + x.b*x.b < y.a*y.a + y.b*y.b) {
		return true;
	}
    	else {
		return false;
	}
}


int main() {
	int n;//指令个数
	while (cin >> n) {
		//存储复数的容器
		vector<Complex> complex_vector;
		string zhiling;
		for (int i = 0; i < n; i++) {//输入各个指令
			cin >> zhiling;
			if (zhiling == "Pop") {
				if (complex_vector.empty() == true) {
					cout << "empty" << endl;
				}
				else {
					//如果不为空,输出最大的复数
					Complex max = complex_vector[complex_vector.size() - 1];
					cout << max.a << "+i" << max.b << endl;
					//删除这个复数
					complex_vector.pop_back();
					//输出容器大小
					cout << "SIZE = " << complex_vector.size() << endl;
				}

			}
			else {
				int aa,bb;
				scanf("%d+i%d", &aa, &bb);
				complex_vector.push_back(Complex(aa, bb));
				//然后排序
				sort(complex_vector.begin(), complex_vector.end(), comp);
				cout << "SIZE = " << complex_vector.size() << endl;

				
			}
		}
	}
	return 0;
}

day05

二进制数

又是写了垃圾代码的一天...

#include <iostream>

using namespace std;

string dec_to_binary(int &x)
{
    if (x==0)
    {
        return to_string(0);
    }
    
    int shang=x/2;
    int yushu=x%2;
    string binary=to_string(yushu);
    while (shang!=0)
    {
        yushu=shang%2;
        binary.append(to_string(yushu));
        shang=shang/2;
    }
    
    string s(binary.rbegin(),binary.rend());
    
    return s;
}

int main()
{
    int x;
    string binary;
    while (cin >> x)
    {
      
        binary = dec_to_binary(x);
        cout << binary << endl;
    }

    return 0;
}

哈夫曼树

#include <iostream>
#include <algorithm>
using namespace std;

int main()
{

    int n;
    while (cin >> n)
    {
        int *arr = new int[n];
        int temp = n;
        int i = 0;
        int x;
        while (temp--)
        {
            scanf("%d", &x);
            arr[i++] = x;
        }

        //将数组arr从小到大排序一下;
        int sum = 0;

        for (int i = 0; i < n - 1; i++)
        {
            sort(arr + i, arr + n);
            arr[i + 1] = arr[i] + arr[i + 1];
            sum += arr[i + 1];
        }
        cout << sum << endl;
    }

    return 0;
}

这题本来把哈夫曼树的求法弄错了...

posted @ 2021-01-13 17:10  four1er  阅读(284)  评论(0)    收藏  举报