算法导论oj汇总

13 篇文章 2 订阅
2 篇文章 0 订阅

Remove K digits

Description
A set has the following elements: 1, and x. If x is in the set, then (2 * x + 1) and (4 * x + 5) are also in the set.
For example, because 1 is in the set, 3=(2 * 1 + 1) and 9=(4 * 1 + 5 )are also in the set.
Take out the smallest M elements in the set and combine them into a multi-digit number in ascending order. Now it is required to remove K digits to make the remaining number maximum. Your program should output the multi-digit numbers before and after removal.
Input
The input contains two integers: M(The number of set elements that make up the multi-digit number) and K(the number of digits to be removed)
M ∈ [1, 30000]
K is positive and not larger than the digits of the number before removal.
Output
The output has two lines. The first line is the multi-digit number before removal, and the second line is the multi-digit number after removal.

样例

输入:
5 4
输出:
137915
95

c++:

#include<iostream>
#include<queue>
#include<string>
#include<stack>
using namespace std;

priority_queue<int, vector<int>, greater<int> > q;//Type 就是数据类型,Container 就是容器类型(Container必须是用数组实现的容器,比如vector,deque等等,但不能用 list。STL里面默认用的是vector),
//Functional 就是比较的方式,当需要用自定义的数据类型时才需要传入这三个参数,使用基本数据类型时,只需要传入数据类型,默认是大顶堆
string str = "";
string ans = "";

void judge(int N) {
	

	if (N == 0) {
		cout << str;
		return;
	}
	if (N == str.size()) {
		cout << 0;
		return;
	}
	deque<int> dq;
	dq.push_back(str[0]-'0');
	int i = 1;
	while(i < str.size()) {
		 while (!dq.empty() && str[i] - '0' > dq.back() && N > 0) {
			 dq.pop_back();
			 N--;
		 }
		 dq.push_back(str[i] - '0');
		 i++;

	}
	while (N > 0) {
		N--;
		dq.pop_back();
	}
	while (!dq.empty()) {
		ans += to_string(dq.front());
		dq.pop_front();
	}
	cout << ans;
}


int main() {
	int M, N;
	cin >> M >> N;
	q.push(1);
	for (int i = 0; i < M; ++i) {
		int t = q.top();
		str = str + to_string(t);
		q.pop();
		q.push(2 * t + 1);
		q.push(4 * t + 5);
	}
	cout << str << endl;
	judge(N);
	return 0;
}

java:(oj只有40分,显示cpu超时)

import java.util.Scanner;
import java.util.Stack;
import java.util.NoSuchElementException;
import java.util.PriorityQueue;

public class Main {

	public static void main(String[] args) {
		PriorityQueue<Integer> q = new PriorityQueue<>();
		String str, ans;
		str = "";
		ans = "";
		Scanner sc = new Scanner(System.in);
		int M, N;
		M = sc.nextInt();
		N = sc.nextInt();
		q.add(1);
		for (int i = 0; i < M; ++i) {
			int t = q.peek();
			str += String.valueOf(t);
			q.remove();
			q.add(2 * t + 1);
			q.add(4 * t + 5);
		}
		System.out.println(str);
		judge(N, str);
		return;

	}

	private static void judge(int N, String str) {
		String ans = "";
		//无删除
		if (N == 0) {
			System.out.print(str);
			return;
		}
		//全部删除
		if (N == str.length()) {
			System.out.print("0");
			return;
		}
		Stack<Integer> dq = new Stack<Integer>();
		dq.add(str.charAt(0) - '0');
		int i = 1;
		while (i < str.length()) {
			try {// while and for diffence in efficiency?A:基本没差
				while (str.length()>1 && !dq.empty()
						&& str.charAt(i) - '0' > dq.lastElement() && N > 0) {
					dq.pop();
					N--;
				}
			} catch (NoSuchElementException e) {
				System.out.println("Error");
			}
			dq.add(str.charAt(i) - '0');
			++i;
		}
		while (N > 0) {
			--N;
			dq.pop();
		}
		while (!dq.empty()) {
			ans += dq.firstElement().toString();
			dq.removeElementAt(0);
		}
		System.out.print(ans);

	}
}

Pocket Money

Description
John decided to give Tom some pocket-money every week. John has some coins with N different normal values. Each value can divide all the other values that are larger than it. He wants to give Tom at least C cents each week with a given set of coins. Please help John calculate how many weeks at most he can give.
For instance:
John wants to give Tom 6 cents a week. He has 100 coins of 1 cent(X), 120 coins of 5 cents(Y), and one coin of 10 cents(Z). John can over give Tom a Z for one week, then two Ys a week for the next 10 weeks. For the last 100 weeks, he can give Tom an X and a Y a week. That’s a total of 111 weeks.
Constraints
N ∈ [1, 20]
C ∈ [1, 100000000]
The normal value V of each coin: V ∈ [1, 100000000]
The number of coins of each value : B ∈ [1, 1000000]

All the input integers are in the range of type ’int’.

input First line: two integers separated by spaces: N(number of
different normal values) and C(The amount of pocket money John wants
to give each week).

Lines 2 to N + 1: each line has two integers representing coins of one
d value: the value V and the number of coins of that value B.

output A single integer indicating the maximum number of weeks John
can give Tom pocket money for at least C cents per week.

样例

输入:
3 6
10 1
1 100
5 120
输出:
111

#include <iostream>
#include <utility>
#include <algorithm>
#include <vector>
#include <math.h>
using namespace std;
int main(){
	int n,minmn;
	cin >> n >> minmn;
	int ans = 0 ;
	pair<int,int> coin;
	vector<pair<int,int>> pocket;
	for(int i = 0; i < n; ++i){
		cin >> coin.first >> coin.second;
		pocket.push_back(coin);
	}
	sort(pocket.begin(),pocket.end());
	
	while(!pocket.empty()){
		int temp = minmn;
		for(int i = pocket.size() - 1;i >= 0; --i){
			pair<int,int>& tmp = pocket.at(i);
			//从小于最小零钱的最大面额硬币开始取,和恰好为最小零钱时,则可直接使用,不用再用小面额的硬币凑。 
			while(tmp.first <= temp && tmp.second > 0){
				temp -= tmp.first;
				--tmp.second;
			} 
			//该种硬币用完 
			if(tmp.second == 0){
				pocket.erase(pocket.begin() + i);
			}
		}
			//用当前存在的最小面额的硬币凑,使总值超过最小零钱 
			if(temp > 0){
				for(int j = 0; j < pocket.size(); ++j){
					pair<int,int>& tmp = pocket.at(j);
					while(temp > 0 && tmp.second > 0){
						temp -= tmp.first;
						--tmp.second;
					}
					if(tmp.second == 0){
						pocket.erase(pocket.begin() + j);
					}
					if(temp <= 0){
						break;
					}
				}
				
			}
			//钱不够 
			if(temp > 0){
				break;
			}
			else{
				++ans;
			}
		
			
			
		
	}
	cout << ans << endl;
	return 0;
	
	
	
	

}
//因爲凑夠最少零錢minmn的組合并不固定,所以不能一次凑夠很多個minmn ,要分成一個一個的去實現。 

King of In-volve

question description
Daniel is a student at College of Computer Software. He is the ‘Top’ student and he loves study.
Daniel has taken all the courses this semester. As a result, he has got lots of assignments to do. By tradition, most students spend their time on playing and hand in their assignments at the last minutes. As a ‘Top’ student, Daniel can complete these assignments easily, so he is trying to get the bonus points.
For example, the course ‘Fundamental Database’ offers 10 bonus points for those who finish the first assignment within 10 days.
Daniel will try to get as much bonus points as possible, but he can only complete one assignment a day.
Now please tell Daniel how many bonus points he can get. He also wants to know how much effort he has to spent on bonus points of each course.
Input
First line is a number N, indicating how many assignments Daniel has.
Lines 2 to N+1: each line describing an assignment, in the format (bonus points, DDL of bonus, name of the course, effort) (int, int, string, int), separated by space.
(The name of course is a single word, no space.)
Output
First line: the max bonus points Daniel can get.
Followed by several lines: in the format (name of the course, effort) (string, int), separated by space.
Print the course in lexicographical order. If Daniel doesn’t get any bonus points of a course, don’t print it.
If there are multiple assignments of a same course, print the course name and the sum of the efforts. Do not print multiple lines.

样例

input:
6
20 2 statistics 10
10 1 database 30
50 2 database 40
30 1 statistics 10
1 1 Python 100
1 2 Python 100
output:
80
database 40
statistics 10

#include <iostream>
#include <string>
#include <utility>
#include <algorithm>
#include <queue>
#include <vector>

using namespace std;

struct subject{
	int bonus;
	int ddl;
	string course;
	int effort;
};
//按ddl排序,由大到小(截止日期晚的先处理),ddl相同的按bonus由大到小排序 
static bool cmpDDL(const subject& s1, const subject& s2){
	if(s1.ddl != s2.ddl){
		return s1.ddl > s2.ddl;
	}
	else{
		return s1.bonus > s2.bonus;
	}
}



//字典序由小到大 
static bool cmpLx(const subject& s1, const subject& s2){
	return s1.course < s2.course;
}

class compare{
	public:
		bool operator()(subject& s1, subject& s2) const{
			//结果按字典序由小到大排序 
			if(s1.bonus == s2.bonus){
				return s1.course > s2.course;
			}
			//结果按bonus由大到小排序 
			return s1.bonus < s2.bonus;
		} 
};


int main(){
	int N, bonus, ddl, effort;
	string course;
	cin >> 	N;
	vector<subject> s;
	int max = 0;
	int maxdate = 0;
	
	for(int i = 0; i < N; ++i){
		cin >> bonus >> ddl >> course >> effort;
		struct subject a = {bonus, ddl, course, effort};
		s.push_back(a);
		if (ddl > maxdate) maxdate = ddl; 
	}
	sort(s.begin(),s.end(),cmpDDL);
	priority_queue<subject, vector<subject>, compare> q;
	vector <subject> result;
	while(maxdate){
		//将最晚截止的任务压入队列中(按bonus排序,bonus大的在队头) 
		while(s.size() && s[0].ddl == maxdate){
			q.push(s[0]);
			s.erase(s.begin());
		}
		if(!q.empty()){
			struct subject temp = q.top();
			max += temp.bonus;
			struct subject a = {1, 1, temp.course, temp.effort};
			bool find = false;
			//合并结果中相同的课程 
			for(int i = 0; i < result.size(); ++i){
				if(result[i].course == temp.course){
					result[i].effort += temp.effort;
					find = true;
					break; 
				}
			}
			if(!find) result.push_back(a);
			q.pop();
		}
		maxdate--;
	}
	sort(result.begin(), result.end(), cmpLx); 
	cout  << max << endl;
	for(int i = 0; i < result.size(); ++i){
		cout << result[i].course << " " << result[i].effort << endl;
	}
	return 0;
	
	
	
}

Singer Tom(最小间隔最大化)

question description
Description

Tom finally realized how important time management is, so he went back
in time and began to schedule it. This time, he can complete all T
assignments in N days (The dates that can be arranged for assignments
are indicated by numbers x1, x2, …, xN). For his absolute strength
and self-confidence, he just prepared each assignment for one day.
Besides, considering his singing hobby, Tom decided to insert some
days for singing between two assignments. Please write a program to
calculate the maximum number of minimum consecutive days between two
assignments that he can arrange for singing.

Constraints

N ∈ [2, 100000]

T ∈ [2, N]

x1, x2, …, xN∈ [0, 10000000]

All the input integers are in the range of type ’int’.

Input

First line: two integers separated by spaces: N(Total number of
available days that Tom can arrange for assignments ) and T(number of
assignments).

Lines 2 to N + 1: each line has one integer i, representing that the
ith day is available for one assignment. These dates are disordered.

Output

A single integer indicating the maximized minimum number of
consecutive days between two assignments.

样例

input: 5 3 1 2 8 4 9
output: 3

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


int n,m;
int* a;


bool judge(int x){
	int last = 0;
	for(int i = 1; i < m; ++i){
		int cnt = last + 1;
		while(cnt < n && a[cnt] - a[last] < x){
			cnt++;
		}
		//x偏大 
		if(cnt == n)return false;
		last = j;
	}
	//x偏小或刚好 
	return true;
}

int main(){
	cin >> n >> m;
	a = new int[n];
	for(int i = 0; i < n; ++i){
		cin >> a[i];
	}
	sort(a,a + n);
	int left = 0;
	int right = a[n - 1] ;
	while(left < right){
		int mid = (left + right + 1) >> 1;
		//预估的最小间隔偏小 
		if(judge(mid)){
			left = mid;
		}
		//预估的最小间隔偏大 
		else{
			right = mid - 1;

		}
		
	}
	cout << right;
	return 0;
}

Singer Tom2

我可真是沒想到这玩意儿还会有后续…

question description Description

As we all know, Tom loves singing songs. Recently, he found a KTV that
meets his requirements. The billing rules are as follows: The KTV
charges $10 for the first 4 hours. For the 5th to the 8th hour, the
charge is $2 per hour. After 8 hours, the charge is $2.4 per hour.

Example 1: Tom took 3 hours and he paid $10 for it.

Example 2: Tom took 6 hours and he paid $14 for it.

Example 3: Tom took 10 hours and he paid $22.8 for it.

But Tom is very clever. Instead of using this weak method mentioned
above, he can divide his time to pay less.

For example, Tom would sing 16 hours. The weak method will cost him
$37.2. But if Tom divided it into two duration of 8 hours, he would
pay $18 for each duration. That’s a total of $36.

Now Tom’s time for singing is provided, please help him calculate the
minimum cost.

(Tom is capable of singing songs for infinity time, don’t worry about
that.)

Input

The first line is a number T, indicating how many test cases there
are.

Line 2 to T+1: an integer H, the total time Tom would sing.

Output

For each test case, print the minimum cost in one line.

Constraints

T ∈ [1, 100]

H ∈ [1, 100000000]

样例1

input:
3 3 9 16
output:
10
20.4
36

package singer2;

import java.util.*;
import java.math.BigDecimal;


public class Main {

	public static void main(String[] args) {
		int T;
		Scanner input = new Scanner (System.in);
		T = input.nextInt();
		int totTime = 0;
		double[] ans = new double[T];
		
		for(int i = 0; i < T; ++i) {
			double fee = 0;
			totTime = input.nextInt();
			if(totTime <= 4) {
				fee = 10;
			}
			else if(totTime <= 8 && totTime > 4) {
				fee = 10 + (totTime - 4)*2;
			}
			else if(totTime > 8) {
				int temp1 = totTime % 8;
				int temp2 = totTime / 8;
				if(temp1 == 0) {
					fee = temp2 * 18;
				}
				else if(temp1 <= 4 && temp1 >= 1) {
					fee = temp2 * 18 + temp1 * 2.4;
				}
				
				else {
					double t1 = (temp1-4)*2 + 10;
					double t2 = temp1 * 2.4;
					if(t1 > t2) {
						fee = temp1 * 2.4 + temp2*18;
					}
					else {
						fee = (temp1 - 4)*2 + 10 + temp2*18;
					}		
				}
			}
			else {
				System.out.print("error");
			}
			ans[i] = fee;
		}
		for(int i = 0 ; i < T; ++i) {
			if((int)ans[i] == ans[i]) 
				System.out.println((int)ans[i]);
			
			else {
				BigDecimal t = new BigDecimal(ans[i] + "");
				String s = t.toPlainString();
				System.out.println(s);
			}
				
		
		}
		
		
		

	}

}

Schedule Online Courses

没想到吧,还有后续…

question description Description

As we all know, Daniel loves study. This semester, the university
offers a lot of online courses. Daniel can focus on only one online
course. In other words, he can’t take two online courses at the same
time.

Daniel wants to take online courses as much as possible. Please help
him calculate the maximum number of online courses he can take.

Input

The first line is a number T, indicating how many test cases there
are.

For each test case: the first line is a number N, indicating how many
online courses there are. Followed by N lines, each describing the
start(S) and end(E) time of one course.

Output

For each test case, print the maximum number of online courses Daniel
can take in one line.

Constraints

T ∈ [1, 100] N ∈ [1, 100] E ∈ [1, 100] For every pair of (S, E), S < E

样例1

input:
2 2 1 3 4 5 12 1 3 3 4 0 7 3 8 15 19 15 20 10 15 8 18 6 12 5 10
4 14 2 9
output:
2 5

java实现:

import java.util.Scanner;
public class Main {

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int T = in.nextInt();
		int[] ans = new int[T];
		for(int i = 0; i < T; ++i) {
			int n = in.nextInt();
			Pair[] course = new Pair[n];
			for(int j = 0; j < n; ++j) {
				course[j] = new Pair();//这个不能少,必须要单独初始化每一个类对象
				int start, end;
				start = in.nextInt();
				end = in.nextInt();
				course[j].setFirst(start);
				course[j].setSecond(end);
			}
			sort(course, n);
			int answer = 0;
			int last = 0;
			for(int k = 0; k < n; ++k) {
				if(course[k].getFirst() >= last) {
					last = course[k].getSecond();
					answer++;
				}
			}
			ans[i] = answer;
			
		}
		for(int q = 0; q < T; ++q) {
			System.out.println(ans[q]);
		}
		

	}
	//以结束时间由小到大排序
	public static void sort(Pair[] p, int n) {
		for(int i = 0; i < n; ++i) {
			for(int j = i + 1; j < n; ++j) {
				if(p[i].getSecond() > p[j].getSecond()) {
					Pair temp = p[i];
					p[i] = p[j];
					p[j] = temp;
				}
			}
		}
	}


}
//因为我找不到javafx.util这个包所以就自己建了一个pair类
class Pair{
	private int first;
	private int second;
	
	public Pair(){
		first = 0;
		second = 0;
	}
	
	public int getFirst() {
		return first;
	}
	public void setFirst(int first) {
		this.first = first;
	}
	public int getSecond() {
		return second;
	}
	public void setSecond(int second) {
		this.second = second;
	}
	
}

c++实现:

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

typedef pair<int, int> course;


//结束时间早的在前
bool compare(course a,course b) {
	return a.second < b.second;
}

int main() {
	int n;
	cin >> n;
	int* ans = new int[n];
	for (int i = 0; i < n; ++i) {
		int m;
		cin >> m;
		course* p = new course[m];
		for (int j = 0; j < m; ++j) {
			cin >> p[j].first >> p[j].second;
		}
		sort(p, p + m, compare);
		int last = -1, answer = 0;
		for (int j=0; j < m; ++j) {
			if (p[j].first >= last) {
				answer++;
				last = p[j].second;
			}
		}
		ans[i] = answer;
	}
	for (int i = 0; i < n; ++i) {
		cout << ans[i];
		if (i != n - 1) cout << endl;
	}
}


A Game between Tom and Daniel(MST,prim算法)

question description
Description

Daniel and Tom are playing a game. There is an undirected connected
graph. If there is one unique minimum spanning tree (MST) in the
graph, Daniel wins. You should print “Daniel” and the weight of the
MST.

If there are multiple minimum spanning trees in the graph, Tom wins.
You should print "Tom -1 ".

Input:

The first line includes two integers N and M, indicating the number of
nodes and edges in the graph.

Lines 2 to M+1: each line contains three integers x, y and d,
indicating an edge in the graph. X and y are the vertices of the edge.
D is the weight of the edge.

Output:

If there is one unique MST in the graph, outputs “Daniel” and the
weight of the MST in one line, separated by space. If not, print “Tom
-1”.

Constraints:

For every two nodes, there is at most one edge.

n ∈ [1, 100]

d ∈ [1, 100000]

sample

样例1
input: 4 4 1 2 2 2 3 2 3 4 2 4 1 2
output: Tom -1
样例2
input: 2 1 1 2 1 output: Daniel 1

c++

#include<stdio.h>
#include<iostream>
#include<string.h>
using namespace std;

const int INF = 100000;
const int MAXN = 101;
int vis[MAXN], map[MAXN][MAXN], low[MAXN];
int flag, N;
int answer;

void prim() {
	memset(vis, 0, sizeof(vis));
	int temp, k;
	answer = 0;
	flag = 1;
	vis[2] = 1;//从2开始访问 
	//low用于记录 U-V到V的最小距离 
	for (int i = 1; i <= N; ++i)low[i] = map[2][i];
	for (int i = 1; i < N; ++i) {
		temp = INF;
		
		//用temp记录当前U-V与V的最小距离 
		for (int j = 1; j <= N; ++j) {
			if (!vis[j] && low[j] < temp) 
				temp = low[k = j];
		}
		int x = 0;
		
		//x记录将要加入V的点与U-V中距离最短的路径条数 
		for (int j = 1; j <= N; ++j) {
			if (vis[j]&&map[k][j] == temp)++x;
			if (x > 1) {
				flag  = 0;
				return;
			}
		}
		//将k加入V 
		vis[k] = 1;
		answer += temp;
		//更新最短距离
		for (int j = 1; j <= N; ++j) {
			if (!vis[j] && map[k][j] < low[j])
				low[j] = map[k][j];
		}
	}

}
int main() {
	int E, st, ed, dis;
	memset(map, INF, sizeof(map));
	scanf("%d %d", &N, &E);
	while (E--) {
		cin >> st >> ed >> dis;
		if (dis < map[st][ed])
			map[st][ed] = map[ed][st]= dis;
	}
	prim();
	if (flag) {
		printf("Daniel %d\n", answer);
	}
	else printf("Tom -1\n");
	return 0;
}

Luggage Problem(动态规划)

question description
Description:

Tom is planning a trip. His luggage can hold at most M kg. He has N
items weighing W1, W2, W3, …, and Wn. The values of the items are
V1, V2, V3, …, and Vn.

Please give the maximum value of the items he can take.

Constraints:

M ∈ [1, 200]

N ∈ [1, 30]

Input:

The first line includes two integers M and N, indicating the maximum
capacity of the luggage and the number of items.

Lines 2 to N+1: each line contains two integers Wi, Vi, indicating the
weight and the value of it.

Output:

Print an integer indicating the maximum value of items he can take.

样例

input: 10 4 2 1 3 3 4 5 7 9 output: 12

c++:

#include <iostream>
#include <algorithm>
#include <string.h>

using namespace std;

const int N = 32;
int w[N], v[N], d[N];

int main(){
	memset(d, 0, sizeof(d));
	memset(w, 0, sizeof(w));
	memset(v, 0, sizeof(v));
	int maxw, n;
	cin >> maxw >> n;
	//d存储的是i重量的东西的最大价值
	for(int i = 1; i <= n; ++i){
		cin >> w[i] >> v[i];
		for(int j = maxw; j >= w[i]; --j){
			d[j] = max(d[j], d[j - w[i]] + v[i]);
		}
	}
	cout << d[maxw] << endl;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值