Day02———排序,折半,huffman

problem A

输入n(n<=100)个整数,按照绝对值从大到小排序后输出。题目保证对于每一个测试实例,所有的数的绝对值都不相等。

Input

输入数据有多组,每组占一行,每行的第一个数字为n,接着是n个整数,n=0表示输入数据的结束,不做处理。

Output

对于每个测试实例,输出排序后的结果,两个数之间用一个空格隔开。每个测试实例占一行。

Sample Input

3 3 -4 2
4 0 1 2 -3
0

Sample Output

-4 3 2
-3 2 1 0

解题思路:

这道题可以用一个简单的冒泡排序,也可以用其他的排序方式如快速排序,选择排序,插入排序等等,因为有负数的输入,所以我们可以在比较时直接用abs返回负数的绝对值,再对其进行排序最终逆序输出,就得到了想要的结果。

AC代码如下:
#include<iostream>
#include<algorithm>
using namespace std;
int a[10010];
int main()
{	
	int n;
	int flag = 0;
	while (cin >> n&&n)
	{
		for (int i = 0; i < n; i++)
		{
			cin >> a[i];


		}
		for (int i = 0; i < n; i++)
		{
			flag = 0;
			for (int j = 1; j < n - i; j++)
			{
				if (abs(a[j ]) < abs(a[j-1]))
				{
					flag = 1;
					swap(a[j ], a[j-1]);
					

				}
				

			}

			if (flag == 0)break;

		}
		for (int i = n-1; i >=1; i--)
		{

			cout << a[i] << " ";

		}
		cout << a[0] << endl;




	}

	return 0;

}

Problem B-4 Values whose Sum is 0

The SUM problem can be formulated as follows: given four lists A, B, C, D of integer values, compute how many quadruplet (a, b, c, d ) ∈ A x B x C x D are such that a + b + c + d = 0 . In the following, we assume that all lists have the same size n .

Input

The first line of the input file contains the size of the lists n (this value can be as large as 4000). We then have n lines containing four integer values (with absolute value as large as 2 28 ) that belong respectively to A, B, C and D .

Output

For each input file, your program has to write the number quadruplets whose sum is zero.

Sample Input

6
-45 22 42 -16
-41 -27 56 30
-36 53 -37 77
-36 30 -75 -46
26 -38 -10 62
-32 -54 -6 45

Sample Output

5
Hint
Sample Explanation: Indeed, the sum of the five following quadruplets is zero: (-45, -27, 42, 30), (26, 30, -10, -46), (-32, 22, 56, -46),(-32, 30, -75, 77), (-32, -54, 56, 30).

解题思路:

给定一个四列数组要求其中a+b+c+d=0有多少个情况,这道题可以用二分查找来解决,化解为a+b=-(c+d),先求出 第一列和第二列的和的所有可能再对其进行排序,这里定义一个大于等于4000X4000的数组来存储这些和,再通过upper_bound(a,a+n,x)-a与lower_bound(a,a+n,x)-a来找到相同的个数(因为之前对b[x]进行排序了的)然后再将相同的个数一起加上就解决了这个问题。

AC代码如下:

#include<iostream>
#include<algorithm>
using namespace std;
const int maxn = 4;
const int m = 4005;
int a[m][maxn];
int b[16000000];
	int main()
	{
		int n;
		int x = 0;
		cin >> n;
		for (int i = 0; i < n; i++)
		{
			for (int j = 0; j < maxn; j++)
			{
				cin >> a[i][j];


			}


		}
		
		for (int i = 0; i < n; i++)
		{
			int c = a[i][0];
			for (int i = 0; i < n; i++)
			{
				b[x++] = c + a[i][1];


			}


		}
		sort(b, b + x);
		int sum = 0;
		for (int i = 0; i < n; i++)
		{
			int c1 = a[i][2];
			for (int i = 0; i < n; i++)
			{
				int p = upper_bound(b, b + x, -(c1 + a[i][3])) - b;
				int q = lower_bound(b, b + x, -(c1 + a[i][3])) - b;

				sum += p - q;
			}



		}


		cout << sum << endl;


	return 0;
}

Problem C- Fence Repair

Farmer John wants to repair a small length of the fence around the pasture. He measures the fence and finds that he needs N (1 ≤ N ≤ 20,000) planks of wood, each having some integer length Li (1 ≤ Li ≤ 50,000) units. He then purchases a single long board just long enough to saw into the N planks (i.e., whose length is the sum of the lengths Li). FJ is ignoring the “kerf”, the extra length lost to sawdust when a sawcut is made; you should ignore it, too.

FJ sadly realizes that he doesn’t own a saw with which to cut the wood, so he mosies over to Farmer Don’s Farm with this long board and politely asks if he may borrow a saw.

Farmer Don, a closet capitalist, doesn’t lend FJ a saw but instead offers to charge Farmer John for each of the N-1 cuts in the plank. The charge to cut a piece of wood is exactly equal to its length. Cutting a plank of length 21 costs 21 cents.

Farmer Don then lets Farmer John decide the order and locations to cut the plank. Help Farmer John determine the minimum amount of money he can spend to create the N planks. FJ knows that he can cut the board in various different orders which will result in different charges since the resulting intermediate planks are of different lengths.

Input

Line 1: One integer N, the number of planks
Lines 2… N+1: Each line contains a single integer describing the length of a needed plank

Output

Line 1: One integer: the minimum amount of money he must spend to make N-1 cuts

Sample Input

3
8
5
8

Sample Output

34

问题描述:

这道题就是给定几个要去拿给农夫处理的不同长度的木板,切一次花费当前木板总长度的钱,再切一次也要花费下一次木板整体总的钱,要求出他花费的最少的钱,这里可以用一个哈夫曼树的方式求解出花费最少数目的钱。
哈夫曼树:给定n个权值作为n个叶子结点,构造一颗二叉树,若该树的带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树。
哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近。

AC代码如下:

#include<iostream>
#include<queue>
#include<functional>
using namespace std;
int a[21000];
int main()
{
	priority_queue<int, vector<int>, greater<int> >q;
	int n;
	cin >> n;
	for (int i = 0; i < n; i++)
	{

		cin >> a[i];
		q.push(a[i]);

	}
	long long ans = 0;
	while (q.size()>1)
	{
		int min1 = q.top();
		q.pop();
		int min2 = q.top();
		q.pop();

		ans += min1 + min2;
		q.push((min1 + min2));

	}



	cout << ans << endl;



	return 0;

}

Problem D-排序

输入一行数字,如果我们把这行数字中的‘5’都看成空格,那么就得到一行用空格分割的若干非负整数(可能有些整数以‘0’开头,这些头部的‘0’应该被忽略掉,除非这个整数就是由若干个‘0’组成的,这时这个整数就是0)。

你的任务是:对这些分割得到的整数,依从小到大的顺序排序输出。

Input

输入包含多组测试用例,每组输入数据只有一行数字(数字之间没有空格),这行数字的长度不大于1000。

输入数据保证:分割得到的非负整数不会大于100000000;输入数据不可能全由‘5’组成。

Output

对于每个测试用例,输出分割得到的整数排序的结果,相邻的两个整数之间用一个空格分开,每组输出占一行。

Sample Input

0051231232050775

Sample Output

0 77 12312320

解题思路:

首先输入应放入一个字符数组中,然后建立一个while循环依次去找这个字符数组中的5,如果没有找到则把当前数字通过now=now*10+str[i]-'0’化为整数形式,再存入一个整型数组中,循环完毕对当前整型数组排序,输出数字隔一个空格再输出一个数字,从而完成输出。

AC代码如下:

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 1005;
char str[maxn];
	int main()
	{
		while (cin >> str){
			
			int ans[maxn];
			memset(ans, 0, sizeof(ans));
			int x = 0;
			int index = 0;
			int count = 0;
			int now = 0;
			while (str[index])
			{
				if (str[index] == '5')
				{
					if (count)
					{
						ans[x++] = now;
						now = 0;
						count = 0;

					}


				}

				else{
					count++;
					now = now * 10 + str[index] - '0';

					


				}

				



				index++;
			}
			if (count)ans[x++] = now;//循环完了没找到5的

			sort(ans, ans + x);
			for (int i = 0; i < x - 1; i++)
			{
				cout << ans[i] << " ";


			}

			cout << ans[x-1] << endl;
		}
		return 0;

}

E - Safe Or Unsafe

Javac++ 一天在看计算机的书籍的时候,看到了一个有趣的东西!每一串字符都可以被编码成一些数字来储存信息,但是不同的编码方式得到的储存空间是不一样的!并且当储存空间大于一定的值的时候是不安全的!所以Javac++ 就想是否有一种方式是可以得到字符编码最小的空间值!显然这是可以的,因为书上有这一块内容–哈夫曼编码(Huffman Coding);一个字母的权值等于该字母在字符串中出现的频率。所以Javac++ 想让你帮忙,给你安全数值和一串字符串,并让你判断这个字符串是否是安全的?

Input

输入有多组case,首先是一个数字n表示有n组数据,然后每一组数据是有一个数值m(integer),和一串字符串没有空格只有包含小写字母组成!

Output

如果字符串的编码值小于等于给定的值则输出yes,否则输出no。

Sample Input

2
12
helloworld
66
ithinkyoucandoit

Sample Output

no
yes

解题思路:

这道题可以看作是一个哈夫曼树,要找安全序列就要找其权值,再找到它的最优路径,如果最优路径小于安全值则输出yes,否则输出no

AC代码如下:

#include<iostream>
#include<queue>
#include<algorithm>
#include<string>
#include<cstring>
#include<functional>
using namespace std;
int a[10000];
int main()
{	
	
	
	int n;
	string str;
	cin >> n;
	int num;
	priority_queue<int, vector<int>, greater<int>>q;
	while (n--)
	{
		
	
		cin >> num>>str;
		memset(a, 0, sizeof(a));

		for (int i = 0; i < str.size(); i++)
		{
			a[str[i] - 'a']++;
			

		}

		for (int i = 0; i < 26; i++)
		{
			if (a[i])
				q.push(a[i]);

		}
		int ans=0;
		while (q.size()>1)
		{
			int m1 = q.top();
			q.pop();
			int m2 = q.top();
			q.pop();
			
			ans += m1 + m2;
			q.push((m1 + m2));


		}
		if (!ans)
		{
			ans = q.top();
			
		}
		while (!q.empty())
		{
			q.pop();

		}

		if (ans <= num)
		{
			cout << "yes" << endl;

		}
		else
		{
			cout << "no" << endl;
		}



	}






	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值