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);
}
}
不行不行,既然遇到了不会的点还是搞清楚吧,遇到一个解决一个,剩下的两道题先不写了,容我去看看什么叫前缀和...
大概懂了,就是用变求和为求差,避免重复的计算
我妈催我洗澡了,直接把别人的搬过来吧
#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;
}
这题本来把哈夫曼树的求法弄错了...


浙公网安备 33010602011771号