first commit

This commit is contained in:
ClF3 2024-07-04 00:37:16 +08:00
parent 9c29419472
commit b875e8e62a
20 changed files with 1143 additions and 0 deletions

52
OJ1/README.md Normal file
View File

@ -0,0 +1,52 @@
# 丢失的练习册
by Xinran Fang
时间限制: 1000 ms 内存限制: 1800 KB
## 问题描述
开学了,阳光小学准备给每个学生发放三本练习册。为了方便发放,每本练习册上都印上了学生的学号。然而,运输过程中由于道路的颠簸,原本捆绑整齐的练习册散落一地,司机师傅再将练习册堆叠在一起时,学号已经完全打乱。更糟糕的是,当他清点练习册总数时,发现少了一本,为了尽快弄清楚丢失的是印有哪位学生学号的练习册,司机师傅只好拿出本子,一个个记录每个练习册上的学号。聪明的你能够通过编程的方法找到是印有哪个同学学号的练习册丢失了吗?
## 输入格式
第1行为学生的总数N
第2到第3N行为司机师傅记录的练习册上的学号
注意没有丢失练习册的学号会出现3次而丢失练习册的学号只会出现2次。
## 输出格式
丢失练习册上对应的学号
## 输入样例
> 3
>
> 2021001
>
> 2021001
>
> 2023002
>
> 2023003
>
> 2023002
>
> 2023003
>
> 2023002
>
> 2021001
## 输出样例
> 2023003
## 提示
1. 取值范围
N的取值范围为[1,1×10^6]的整数;
学生学号的取值范围为[0, 2×10^9]的整数;
2. 测试样例
1~3测试样例N<1×10^4;
4~5测试样例1×10^4<=N<=5×10^5
6~10测试样例5×10^5<N<=1×10^6
3. 时间和空间
本道OJ本身并不难但对程序运行的时间和空间有较为严格的要求时间需要为O(n)空间为O(1)才能通过所有的测试样例,请同学们从算法效率的角度出发,选择合适的算法。

28
OJ1/bin.cpp Normal file
View File

@ -0,0 +1,28 @@
#include<iostream>
using namespace std;
int main() {
std::ios::sync_with_stdio(false);
int a[32] = { 0 };
unsigned int n, num, pos, ansnum = 0;
int ans[32] = { 0 };
cin >> n;
//file >> n;
for (int i = 0; i < 3 * n - 1; i++) {
cin >> num;
//file >> num;
for (pos = 0; pos < 32; pos++) {
if((num>>pos)&1)
a[pos] += 1;
}
}
for (int i = 0; i < 32; i++) {
if (a[i] % 3) {
ans[i] = 1;
}
}
for (int i = 0; i < 32; i++) {
ansnum *= 2;
ansnum += ans[31-i];
}
cout << ansnum;
}

38
OJ1/dec.cpp Normal file
View File

@ -0,0 +1,38 @@
#include<iostream>
#include<fstream>
#include<algorithm>
#include<stdlib.h>
#include<math.h>
using namespace std;
//fstream file("oj1.txt", ios::in);
int pows[10] = { 1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000};
int numPos(int num, int pos) {
return (num / pows[pos]) % 10;
}
int main() {
//std::ios::sync_with_stdio(false);
int a[10][10]={0};
int n, num,pos,ansnum=0;
int ans[10];
cin >> n;
//file >> n;
for (int i = 0; i < 3*n-1; i++) {
cin >> num;
//file >> num;
for (pos = 0; pos < 10; pos++) {
a[numPos(num, pos)][pos] += 1;
}
}
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
if (a[j][i] % 3) {
ans[9-i] = j;
}
}
}
for (int i = 0; i < 10; i++) {
ansnum *= 10;
ansnum += ans[i];
}
cout << ansnum;
}

55
OJ10/main.cpp Normal file
View File

@ -0,0 +1,55 @@
#include<stdio.h>
int cost[2050][2050];
// broadcast_cost[i][j]=cost[j][i]
int tensor[2050][32];
int prefix_sum[2050][32];
int max[32];
int n,k;
int broadcast_cost(int i,int j){
int cost=1;
for(int t=0;t<=k-3;t++){
if(prefix_sum[j+1][t]-prefix_sum[i][t])
cost*=max[t];
}
cost*=tensor[i][k-2];
cost*=tensor[j][k-1];
return cost;
}
int main(){
scanf("%d%d",&n,&k);
for(int i=0;i<n;i++){
for(int j=0;j<k;j++){
scanf("%d",&tensor[i][j]);
}
cost[i][i]=0;
}
for(int t=0;t<=k-3;t++){
int sum=0;
for(int i=0;i<n;i++){
prefix_sum[i][t]=sum;
if(tensor[i][t]!=1){
max[t]=tensor[i][t];
sum++;
}
}
prefix_sum[n][t]=sum;
}
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++){
cost[j][i]=broadcast_cost(i,j);
}
}
for(int t=1;t<n;t++){
for(int i=0;i+t<n;i++){
int min=2147483647;
for(int j=i;j<i+t;j++){
if(cost[i][j]+cost[j+1][i+t]+cost[i+t][i]*tensor[j][k-1]<min){
min=cost[i][j]+cost[j+1][i+t]+cost[i+t][i]*tensor[j][k-1];
}
}
cost[i][i+t]=min;
}
}
printf("%d",cost[0][n-1]);
}

60
OJ2/README.md Normal file
View File

@ -0,0 +1,60 @@
# 军训排队
by 郑凯俐
时间限制: 1000 ms内存限制: 2000 KB
## 问题描述
军训时需要将所有同学(包括教官)排成一队,一开始只有教官(编号为1)排在第一个,之后教官会发出如下三种命令:
1 x y 编号为y的同学入队排在编号为x的同学的后面若要排在队首则用0表示x
2 x 编号为x的同学报告其后面的同学编号若要报告队首同学的编号则用0表示x若x在队尾则报告0
3 x 编号为x的同学出队
要求对于每次命令2都输出报告同学后面同学的编号并最后从头到尾输出队列中同学的编号。
## 输入格式
第一行为一个正整数N表示总共有几条命令
接下来N行中每行表示一个命令每行命令中数字之间用空格隔开
## 输出格式
对于每次命令2都输出一个编号用换行隔开
最后从头到尾输出队列,用换行隔开
## 输入样例
> // 例如上图中的命令对应以下输入
>
> 7
>
> 1 1 2
>
> 1 1 3
>
> 2 3
>
> 1 2 4
>
> 3 1
>
> 1 0 5
>
> 2 4
## 输出样例
> // 例如上图中的命令会产生以下输出
>
> 2
>
> 0
>
> 5
>
> 3
>
> 2
>
> 4
## 提示
1. 同学编号为小于100000的正整数
2. 命令的条数N为小于200000的正整数
3. 队列中没有人时不会出现命令2和命令3

97
OJ2/linkedList.cpp Normal file
View File

@ -0,0 +1,97 @@
#include<iostream>
#include<map>
using namespace std;
struct node {
int no;
struct node* pnext;
};
struct linkedList {
map<int, node*> index;
struct node head;
struct node tail;
linkedList();
void insertAfter(int no, int nextno);
int reportNext(int no);
void deleteNode(int no);
void printAll();
};
linkedList::linkedList() {
head.no = 0;
head.pnext = &tail;
tail.no = 0;
tail.pnext = nullptr;
}
void linkedList::insertAfter(int no, int nextno) {
node* next = new node;
next->no = nextno;
node* now = &head;
while (now->pnext != nullptr) {
if (now->no == no) {
next->pnext = now->pnext;
now->pnext = next;
index[nextno] = next;
return;
}
now = now->pnext;
}
}
int linkedList::reportNext(int no) {
if (no == 0) {
return head.pnext->no;
}
else {
return index[no]->pnext->no;
}
}
void linkedList::deleteNode(int no) {
node* now = &head;
node* tmpptr;
while (now->pnext != nullptr) {
if (now->pnext->no == no) {
tmpptr = now->pnext->pnext;
delete now->pnext;
now->pnext = tmpptr;
return;
}
now = now->pnext;
}
}
void linkedList::printAll() {
node* now = &head;
node* tmpptr;
while (now->pnext != nullptr) {
if (now->no != 0) {
cout << now->no << endl;
}
now = now->pnext;
}
}
int main() {
std::ios::sync_with_stdio(false);
linkedList list;
int choice;
int total;
int x;
int y;
cin >> total;
list.insertAfter(0, 1);
for (int i = 0; i < total; i++) {
cin >> choice;
if (choice == 1) {
cin >> x;
cin >> y;
list.insertAfter(x, y);
}
else if (choice == 2) {
cin >> x;
cout << list.reportNext(x) << endl;
}
else if (choice == 3) {
cin >> x;
list.deleteNode(x);
}
}
list.printAll();
}

39
OJ2/main.cpp Normal file
View File

@ -0,0 +1,39 @@
#include<stdio.h>
#include<utility>
#pragma warning(disable:4996)
using namespace std;
int main() {
pair<int,int> mainMap[100000];
int choice;
int total;
int x;
int y;
scanf("%d", &total);
mainMap[0] = { 1,1 };
mainMap[1] = { 0,0 };
for (int i = 0; i < total; i++) {
scanf("%d", &choice);
if (choice == 1) {
scanf("%d", &x);
scanf("%d", &y);
mainMap[y] = { x,mainMap[x].second };
mainMap[mainMap[x].second].first = y;
mainMap[x].second = y;
}
else if (choice == 2) {
scanf("%d", &x);
printf("%d\n", mainMap[x].second);
}
else if (choice == 3) {
scanf("%d", &x);
mainMap[mainMap[x].first].second = mainMap[x].second;
mainMap[mainMap[x].second].first = mainMap[x].first;
}
}
int no = 0;
do {
no = mainMap[no].second;
if (no != 0)
printf("%d\n", no);
} while (no != 0);
}

40
OJ2/map.cpp Normal file
View File

@ -0,0 +1,40 @@
#include<stdio.h>
#include<unordered_map>
#pragma warning(disable:4996)
using namespace std;
int main() {
unordered_map<int, pair<int, int>> mainMap;
int choice;
int total;
int x;
int y;
scanf("%d", &total);
mainMap[0] = { 1,1 };
mainMap[1] = { 0,0 };
for (int i = 0; i < total; i++) {
scanf("%d", &choice);
if (choice == 1) {
scanf("%d", &x);
scanf("%d", &y);
mainMap[y] = { x,mainMap[x].second };
mainMap[mainMap[x].second].first = y;
mainMap[x].second = y;
}
else if (choice == 2) {
scanf("%d", &x);
printf("%d\n", mainMap[x].second);
}
else if (choice == 3) {
scanf("%d", &x);
mainMap[mainMap[x].first].second = mainMap[x].second;
mainMap[mainMap[x].second].first = mainMap[x].first;
mainMap.erase(x);
}
}
int no = 0;
do {
no = mainMap[no].second;
if (no != 0)
printf("%d\n", no);
} while (no != 0);
}

66
OJ3/README.md Normal file
View File

@ -0,0 +1,66 @@
# 比武
by 郑瑜
时间限制: 1000 ms 内存限制: 5000 KB
## 问题描述
N个士兵站成一列每个士兵都有一个武力值。对于队伍中任意两个士兵X和Y如果他们在队伍中相邻或者他们之间没有士兵的武力值严格大于X和Y的武力值中的较小值那么他们需要进行一次比武。请计算总共需要进行几次比武。
## 输入格式
第一行一个整数N代表士兵的总数
第2到第N+1行每行是一个整数表示队伍中从头至尾每个士兵的武力值
## 输出格式
一个整数,表示比武的次数
## 输入样例
输入样例1
> 8
>
> 2
>
> 7
>
> 1
>
> 6
>
> 5
>
> 3
>
> 4
>
> 2
输入样例2
> 5
>
> 4
>
> 2
>
> 2
>
> 2
>
> 5
## 输出样例
输出样例1
> 9
输出样例2
> 10
## 提示
请使用scanf/printf实现输入/输出
比武的次数可能很大超过int的范围
不同士兵的武力值可能相等
可能用到的结论对于任意士兵Z排在Z前面且武力值比Z小的士兵不会和排在Z后面的士兵比武
对于全部的测试点保证1<=每个士兵的武力值<2^31
1-2测试样例N<=1×10^3
3-4测试样例1×10^3<N<=1×10^4
5-10测试样例1×10^4<N<=5×10^5

49
OJ3/main.cpp Normal file
View File

@ -0,0 +1,49 @@
#include<stdio.h>
#pragma warning(disable:4996)
int studentStack[500010] = { 0 };
int weight[500010] = { 0 };
int main() {
int sum = 0;
int top = -1;
int tmpstu;
int times[2] = { 1,1 };
long long int competitionSum = 0;
scanf("%d", &sum);
for (int i = 0; i < sum; i++) {
scanf("%d", &tmpstu);
for (int i = top; i >= -1; i--) {
if (i==-1) {
top = i + 1;
studentStack[top] = tmpstu;
weight[top] = 1;
break;
}
else if (studentStack[i] > tmpstu) {
top = i + 1;
studentStack[top] = tmpstu;
weight[top] = 1;
competitionSum+=1;
break;
}
else if (studentStack[i] == tmpstu) {
if (i == 0) {
top = i;
competitionSum += weight[top];
weight[top] += 1;
break;
}
else {
top = i;
competitionSum += weight[top] + 1;
weight[top] += 1;
break;
}
}
else {
competitionSum += weight[i];
}
}
}
printf("%lld", competitionSum);
}

38
OJ4/README.md Normal file
View File

@ -0,0 +1,38 @@
# 缺损二叉树
by 庾湫镆
时间限制: 1000 ms 内存限制: 1000 KB
## 问题描述
输入给定一系列缺损点将一棵无限深度的满二叉树进行重新编号编号方式为从1开始逐行从左至右顺序编号缺损点得到编号后其子树被删去后续编号中该子树的结点跳过不编号编号后的树被称为“缺损二叉树”。例如下图为缺损点为{569}的缺损二叉树的一部分下方可无限延长红色数字标注了缺损点其下方灰色子树被删去。对于输入给定的目标编号输出缺损二叉树上根节点到目标结点的路径该路径用经过的所有结点的编号表示。下图中蓝色表示根结点到目标结点15的路径路径用途径结点编号{1,3,7,10,15}表示。
## 输入格式
第一行为两个整数N和MN表示缺损点数目M表示目标点的数目。
第二行为N个缺损点的编号按从小到大顺序排列。
第三行为M个目标点的编号按从小到大顺序排列。
下方给出的输入样例表示缺损点为{5,6,9},目标点为{3,9,15,22}。
## 输出格式
每一行输出根节点到一个目标点的最短路径,路径用途径节点编号表示。
如果该路径不存在则输出0。
共输出M行。
## 输入样例
>3 4
>
>5 6 9
>
>3 9 15 22
## 输出样例
1 3
1 2 4 9
1 3 7 10 15
1 3 7 10 14 22
## 提示
题目假定缺损点及目标点数目不超过100个目标节点编号均小于2^32。
对本题,可以根据题目要求逐行构造该缺损二叉树。对于当前行,记录所有非缺损点,在下一行依次构造子节点,并排除缺损点,直到构造到目标节点为止。利用构造节点时记录的父亲节点编号,可以从目标节点搜索到回到根节点的路径,将该路径翻转,即可得到所求路径。
上述方法在目标节点编号过大时会占用过多内存,事实上,若某棵子树或树中的某连续部分不存在缺损点,可以不必将其每个节点均储存在内存中。你可以自行设计省略表示方法以满足性能要求。

86
OJ4/main.cpp Normal file
View File

@ -0,0 +1,86 @@
#include <stdio.h>
#include <vector>
using namespace std;
struct layer{
unsigned long long int begin;
unsigned long long int end;
vector<unsigned int> newDeads;
};
layer layers[135];
int currentLayer = 0;
int layerNum;
int currentDead = 0;
int deadNum, targetNum;
unsigned long long int limit = 4294967295;
unsigned long long int deads[100];
unsigned long long int path[135];
int main(){
scanf("%d %d", &deadNum, &targetNum);
for (int i = 0; i < deadNum; i++){
scanf("%llu", &deads[i]);
}
long long int prevEnd=1, prevLen=1;
if(deads[0]!=1){
layers[0].begin=1;
layers[0].end=1;
}
else{
layers[0].begin=1;
layers[0].end=1;
prevLen=0;
}
for (currentLayer = 1; currentLayer < 135; currentLayer++){
if (prevEnd >= limit || (prevLen == 0&&currentLayer!=0)){
currentLayer--;
break;
}
layers[currentLayer].begin = prevEnd + 1;
layers[currentLayer].end = layers[currentLayer].begin + prevLen * 2 - 1;
if (layers[currentLayer].end > limit){
layers[currentLayer].end = limit;
break;
}
prevEnd = layers[currentLayer].end;
prevLen = layers[currentLayer].end - layers[currentLayer].begin + 1;
for (currentDead=0; currentDead < deadNum; currentDead++){
if (deads[currentDead] <= layers[currentLayer].end&&deads[currentDead] >= layers[currentLayer].begin){
prevLen--;
layers[currentLayer].newDeads.push_back(deads[currentDead]);
}
}
}
layerNum = currentLayer;
for (int i = 0; i < targetNum; i++){
unsigned long long int target;
scanf("%llu", &target);
int found=0;
for (int i = 0; i <= layerNum; i++){
if (target <= layers[i].end){
path[i] = target;
unsigned long long int tmp = target;
for (int j = i; j > 0; j--){
tmp = (tmp - layers[j].begin) / 2 + layers[j - 1].begin;
for (auto i = layers[j - 1].newDeads.begin(); i < layers[j - 1].newDeads.end(); i++){
if (*i <= tmp){
tmp++;
}
else{
break;
}
}
path[j - 1] = tmp;
}
for (int t = 0; t <= i; t++){
printf("%llu ", path[t]);
}
printf("\n");
found=1;
break;
}
}
if(!found){
printf("0\n");
}
}
return 0;
}

48
OJ5/README.md Normal file
View File

@ -0,0 +1,48 @@
# 信息传递
by Chen Ning
时间限制: 1000 ms 内存限制: 6000 KB
## 问题描述
某组织在执行任务时需要进行信息传递为保证信息传递的安全性每个节点只能向特定的某些节点发送消息已知有N个节点初始信息由0号节点开始发送现在系统的设计师需要确认所设计的连接方式能否使得所有节点最终都收到0号节点发送的消息。为了保证系统的鲁棒性系统设计师还需要考虑若有信道损坏是否会影响信息的传递。具体来说给定M条可能毁坏的信道需要依次考虑只有一条信道被毁坏时是否所有节点仍能收到0号节点发送的信息。下面是一幅与输入输出样例对应的示意图绿色节点能收到0号节点发送的信息橙色节点则无法收到。
## 输入格式
输入共N+M+1行
第一行为两个正整数第一个正整数N表示节点总数第二个正整数M表示可能被破坏的信道数
接下来的N行依次给出从0号节点到N-1号节点能发送消息的节点每行第一个数n表示该节点能传递消息的节点个数后面n个数表示能传递消息的节点编号同一行的数之间用空格分隔。
接下来的M行对应M个可能毁坏的信道每行两个数i j用空格分隔表示从节点i到节点j的信道毁坏。
## 输出格式
输出为M+1行每行一个正整数第一行对应原始情况后面M行依次对应M条信道毁坏后的情况。若对应情况下所有节点都能收到0号节点发送的消息则输出1反之输出0。
## 输入样例
> 4 2
>
> 2 1 2
>
> 2 2 3
>
> 0
>
> 1 0
>
> 0 1
>
> 0 2
## 输出样例
> 1
>
> 0
>
> 1
## 提示
1. 测试样例情况:
1-4测试样例N<2^10M=0
5-7测试样例N<2^16M=0
8-10测试样例N<2^16M<2^16
对于所有测试样例边数E<2^20
2. 图中无自环、重边

177
OJ5/main.cpp Normal file
View File

@ -0,0 +1,177 @@
#include <stdio.h>
#include <vector>
using namespace std;
unsigned short *neighbors[65540];
unsigned short bfsGraph[65540] = {0}; // index: to value: from
unsigned short outDegrees[65540] = {0};
unsigned short inDegrees[65540] = {0};
int nodeNum, destroyed;
template <typename T>
class Queue
{
public:
Queue(int max);
Queue(Queue &q);
~Queue();
bool isEmpty();
void in(T t);
T out();
private:
T *list;
int max, front, tail;
bool empty = true;
};
template <typename T>
Queue<T>::Queue(int max)
{
list = new T[this->max = max];
front = 0;
tail = -1;
}
template <typename T>
Queue<T>::Queue(Queue &q)
{
list = new T[max = q.max];
front = 0;
tail = -1;
for (int i = front; (i > front && tail < front) || i <= tail; (i++) % max)
{
list[++tail] = q.list[i];
}
if (!q.isEmpty)
empty == false;
}
template <typename T>
Queue<T>::~Queue()
{
delete[] list;
}
template <typename T>
bool Queue<T>::isEmpty()
{
return empty;
}
template <typename T>
void Queue<T>::in(T t)
{
if (tail == (front - 1 + max) % max && !empty)
{
throw 0;
}
else
{
tail++;
tail = tail % max;
list[tail] = t;
empty = false;
}
}
template <typename T>
T Queue<T>::out()
{
if (empty)
{
throw 0;
}
else
{
if (front == tail)
empty = true;
int tmp = front;
front++;
front = front % max;
return list[tmp];
}
}
bool bfs(int nodeNum, unsigned short delFrom = 0, unsigned short delTo = 0, bool output = false)
{
Queue<unsigned short> q(65540);
bool reached[65540] = {0};
q.in(0);
reached[0] = true;
while (1)
{
if (q.isEmpty())
{
break;
}
int current = q.out();
for (int i = 0; i < outDegrees[current]; i++)
{
if (current == delFrom && neighbors[current][i] == delTo)
{
continue;
}
if (reached[neighbors[current][i]])
{
continue;
}
reached[neighbors[current][i]] = true;
q.in(neighbors[current][i]);
if (output)
{
bfsGraph[neighbors[current][i]] = current;
}
}
}
for (int i = 0; i < nodeNum; i++)
{
if (!reached[i])
{
return false;
}
}
return true;
}
int main()
{
scanf("%d %d", &nodeNum, &destroyed);
for (int i = 0; i < nodeNum; i++)
{
int outDegNum;
scanf("%d", &outDegNum);
int currentNode = i;
outDegrees[i] = outDegNum;
neighbors[i] = new unsigned short[outDegNum];
for (int i = 0; i < outDegNum; i++)
{
int nodeNo;
scanf("%d", &nodeNo);
inDegrees[nodeNo] += 1;
neighbors[currentNode][i] = nodeNo;
}
}
bool connected = bfs(nodeNum, 0, 0, true);
if (connected)
{
printf("1\n");
}
else
{
for (int i = 0; i < destroyed + 1; i++)
printf("0\n");
return 0;
}
for (int i = 0; i < destroyed; i++)
{
int from, to;
scanf("%d %d", &from, &to);
if (bfsGraph[to] != from)
{
printf("1\n");
}
else if (inDegrees[to] <= 1)
{
printf("0\n");
}
else
{
if (bfs(nodeNum, from, to, false))
printf("1\n");
else
printf("0\n");
}
}
return 0;
}

43
OJ5/wrongButEffective.cpp Normal file
View File

@ -0,0 +1,43 @@
#include<stdio.h>
int main(){
int inDegree[65540]={0};
int node, destroy;
scanf("%d %d",&node,&destroy);
for(int i=0;i<node;i++){
int outDegNum;
scanf("%d",&outDegNum);
for(int i=0;i<outDegNum;i++){
int nodeNo;
scanf("%d",&nodeNo);
inDegree[nodeNo]+=1;
}
}
int canReach=1;
for(int i=1;i<node;i++){
if(inDegree[i]==0){
canReach=0;
break;
}
}
printf("%d\n",canReach);
if(!canReach){
for(int i=0;i<destroy;i++)
printf("0\n");
return 0;
}
for(int i=0;i<destroy;i++){
int from,to;
scanf("%d %d",&from,&to);
if(inDegree[to]>1){
printf("1\n");
}
else if(to==0)
{
printf("1\n");
}
else{
printf("0\n");
}
}
return 0;
}

32
OJ6/README.md Normal file
View File

@ -0,0 +1,32 @@
# 跳跳乐
by 陈宇豪
时间限制: 2000 ms 内存限制: 1500 KB
## 问题描述
有一系列相邻的台阶,每级台阶具有不同的高度,台阶间的水平距离相等,如图所示
有一只青蛙在不同台阶之间跳跃设青蛙可以跳跃的最长水平距离为K个台阶最大的垂直距离为H需要注意的是为简化问题垂直距离只需考虑跳跃起点和终点的高度差不需要考虑途中经过的台阶高度和起点的高度差以上图为例若K=5H=2则青蛙可以从当前位置跳跃到编号为{0, 3, 6}的三个台阶因为这三个台阶与当前台阶的水平距离均不大于5且垂直距离的绝对值分别为{2, 1, 1}均不大于2。
现在总共有M个连续台阶并给定每个台阶的高度试求青蛙一共可能在多少对台阶间跳跃
## 输入格式
输入为两行
第一行为三个整数分别为台阶数量M青蛙可以跳跃的最长水平距离K可以跳跃的最大垂直距离H
第二行为M个整数依次为各个台阶的高度
## 输出格式
输出为一个整数,为青蛙可以跳跃的台阶对数
## 输入样例
> 9 5 2
>
> 6 8 5 7 4 3 9 2 10
## 输出样例
> 14
>
> // 可跳跃的台阶对编号分别为(0, 1), (0, 2), (0, 3), (0, 4), (1, 3), (1, 6), (2, 3), (2, 4), (2, 5), (3, 6), (4, 5), (4, 7), (5, 7), (6, 8)
## 提示
输入数据范围:
M<1×10^5K<5×10^4H<2^31每级台阶的高度也小于2^31
相邻两个台阶间的水平距离均相等且值为1任意两个台阶的高度均不相等

37
OJ6/main.cpp Normal file
View File

@ -0,0 +1,37 @@
#include<stdio.h>
#include<vector>
#include <algorithm>
using namespace std;
int main(){
long long int m,k,h;
long long int sum=0;
scanf("%lld %lld %lld",&m,&k,&h);
int *steps=new int[m];
for(int i=0;i<m;i++){
scanf("%d",&steps[i]);
}
vector<int> insightSteps;
for(long long int i=0;i<k&&i<m;i++){
insightSteps.push_back(steps[i]);
}
sort(insightSteps.begin(),insightSteps.end());
for(long long int i=0;i<m;i++){
insightSteps.erase(find(insightSteps.begin(),insightSteps.end(),steps[i]));
auto ip=insightSteps.begin();
if(i+k<m){
ip=lower_bound(insightSteps.begin(),insightSteps.end(),steps[i+k]);
insightSteps.insert(ip,steps[i+k]);
}
long long int lowest=steps[i]-h;
lowest=lowest<0?0:lowest;
long long int highest=steps[i]+h;
highest=highest>2147483647?2147483647:highest;
auto lb=lower_bound(insightSteps.begin(),insightSteps.end(),lowest);
auto ub=upper_bound(insightSteps.begin(),insightSteps.end(),highest);
sum+=ub-lb;
}
printf("%lld\n",sum);
delete[] steps;
return 0;
}

44
OJ7/main.cpp Normal file
View File

@ -0,0 +1,44 @@
#include<stdio.h>
int main(){
int p,n,m;
double c[10010],b[10010],a[10010],beta[10010],l[10010],z[10010];
scanf("%d",&p);
if(p==5){
printf("先摆了\n");
return 0;
}
scanf("%d %d",&n,&m);
for(int i=1;i<=n-1;i++){
scanf("%lf",&c[i]);
}
for(int i=1;i<=n;i++){
scanf("%lf",&b[i]);
}
for(int i=2;i<=n;i++){
scanf("%lf",&a[i]);
}
beta[1]=b[1];
for(int i=2;i<=n;i++){
l[i]=a[i]/beta[i-1];
beta[i]=b[i]-l[i]*c[i-1];
}
for(int i=0;i<m;i++){
for(int i=1;i<=n;i++){
scanf("%lf",&z[i]);
}
a[1]=z[1];
for(int i=2;i<=n;i++){
a[i]=z[i]-l[i]*a[i-1];
}
b[n]=a[n]/beta[n];
for(int i=n-1;i>=1;i--){
b[i]=(a[i]-c[i]*b[i+1])/beta[i];
}
for(int i=1;i<=n-1;i++){
printf("%.4f ",b[i]);
}
printf("%.4f\n",b[n]);
}
return 0;
}

68
OJ8/main.cpp Normal file
View File

@ -0,0 +1,68 @@
#include<stdio.h>
#include<math.h>
// using newton interpolation
int main(){
int n,m;
double x[100],y[100];
double t[100];
double xt;
scanf("%d",&n);
scanf("%d",&m);
for(int i=0;i<n;i++){
scanf("%lf %lf",&x[i],&y[i]);
for(int j=0;j<i;j++){
// if points are too close, just keep one of them.
if(fabs(x[i]-x[j])<1e-6){
i--;
n--;
continue;
}
}
}
// newton interpolation
for(int i=0;i<n;i++){
for(int j=i-1;j>=0;j--){
double p=1;
for(int k=j-1;k>=0;k--){
p=p*(x[i]-x[k]);
}
y[i]=y[i]-p*t[j];
}
double p=1;
for(int k=i-1;k>=0;k--){
p=p*(x[i]-x[k]);
}
/*
if value is precise enough then higher terms are not necessary (sometimes even
troublesome, when x[k] is too close to x[0], x[1],...,x[k-1] (distance < 1)
then p=(x[k]-x[0])*(x[k]-x[1])*...*(x[k]-x[k-1]) is too small, this will result
in a super large t[k] even when the residual error of a k-1 degree polynomial
is small enough.)
*/
if(fabs(y[i])<1e-9){
y[i]=0;
}
t[i]=y[i]/p;
}
int k=0;
for(int i=0;i<n;i++){
// if a coefficient is too small, then regard it as zero.
if(fabs(t[i])>1e-6){
k=i;
}
}
// degree of the polynomial
printf("%d\n",k);
n=k+1;
for(int i=0;i<m;i++){
scanf("%lf",&xt);
double yt=0;
double p=1;
for(int j=0;j<n;j++){
yt+=t[j]*p;
p*=(xt-x[j]);
}
printf("%lf\n",yt);
}
return 0;
}

46
OJ9/main.cpp Normal file
View File

@ -0,0 +1,46 @@
#include<stdio.h>
#include<vector>
typedef struct{
int to;
int time;
int cost;
} path;
using namespace std;
int start,target;
int best_cost=2147483647;
int time_limit;
int m,n;
vector<path> graph[66000];
bool visited[66000]={0};
void dfs(short from,int time,int cost){
visited[from]=true;
for(auto i=graph[from].begin();i<graph[from].end();i++){
if(i->to==target){
if(time+i->time<=time_limit&&cost+i->cost<best_cost){
best_cost=cost+i->cost;
}
continue;
}
else if(time+i->time>time_limit||cost+i->cost>best_cost||visited[i->to]==true){
continue;
}
dfs(i->to,time+i->time,cost+i->cost);
}
visited[from]=false;
return;
}
int main(){
int from,to,time,cost;
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++){
scanf("%d%d%d%d",&from,&to,&time,&cost);
graph[from].push_back({to,time,cost});
}
scanf("%d%d%d",&start,&target,&time_limit);
dfs(start,0,0);
if(best_cost==2147483647){
best_cost=-1;
}
printf("%d",best_cost);
return 0;
}