大白书练习题(持续更新……)UVa & livearchive

博主分享了刷大白书过程中遇到的UVa和livearchive在线评测系统的编程题目,涉及模拟和贪心算法。通过解决不同题目,博主提醒读者注意题目细节,如输入格式、负数结束标志等,并提供了AC代码,包括DNA序列分析、最小矩形覆盖问题等,强调理解和应用算法的重要性。

买了一本大白书,上面的题挺不错的,就准备挨着刷一次,这里记录一下我的刷题之旅以及一些略显2B的错误

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=442

是整理好了的,LA的题目这里面也移植到了UVa


[130821]

UVa 11292 —— The Dragan of Loowater

挺简单的一道模拟题,贪心,总是用可行的最小的骑士去杀龙。所以排序即可

C++ AC Code (1A)

// By Jiangzh
#include <cstdio>
#include <cstring>
#include <algorithm>
const int N = 20000 + 10;

int n,m,dra[N],kni[N];

void solve()
{

	for(int i = 1; i <= n; i++) scanf("%d", &dra[i]);
	for(int i = 1; i <= m; i++) scanf("%d", &kni[i]);
	std::sort(kni + 1, kni + 1 + m);
	std::sort(dra + 1, dra + 1 + n);
	int j = 1, res = 0, flag = 0;
	for(int i = 1; i <= m; i++)
	{
		if(kni[i] < dra[j]) continue;
		res += kni[i];
		if(++j == n+1) { flag = 1; break; }
	}
	if(flag) printf("%d\n", res);
	else printf("Loowater is doomed!\n");
}

int main()
{
	freopen("11292.in", "r", stdin);
	freopen("11292.out", "w", stdout);
	while(scanf("%d%d", &n, &m)==2 && n && m)
	{
		memset(dra, 0, sizeof(dra));
		memset(kni, 0, sizeof(kni));
		solve();
	}
	return 0;
}


[130822]

UVa 11039 —— Hello World!

挺简单的一道题,但是我被输入坑了

最后一句话“Input is terminated by a linecontaining a negative integer.”我没注意看,我还以为是以-1结束,结果是以负数结束。。。。。。

贪心的想法,每次尽可能多的复制(即每次复制所有),log2即可,注意向上取整数

C++ AC Code (3A)

// By Jiangzh
#include <cstdio>
#include <cmath>

int n;

void solve()
{
	int res = ceil(log2(1.0 * n));
	printf("%d\n", res);
}

int main()
{
	freopen("11636.in", "r", stdin);
	freopen("11636.out", "w", stdout);
	int cases = 0;
	while(scanf("%d", &n) == 1 && n>0) 
	{
		printf("Case %d: ", ++cases);
		solve();
	}
	return 0;
}

UVa 11039 —— Building Designing

个人觉得大白书上的翻译不是很好,一开始没有把题目弄懂,结果样例都没过,看看原题才知道到底是什么意思

总之是选出尽可能多的数(顺序随便),然后排列起来,绝对值递增,并且正负交替

按照绝对值排序即可,然后判断正负交替可以用相乘,切忌用原数直接相乘(会暴int的!!)

C++ AC Code (2A)

// By Jiangzh
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>

const int N = 500000 + 10;

int n;
int a[N];

bool cmp(int a, int b)
{
	return abs(a) < abs(b);
}

void solve()
{
	scanf("%d", &n);
	for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
	std::sort(a+1, a+1+n, cmp);
	int last = a[1];
	int res = 1;
	for(int i = 2; i <= n; i++)
	{
		int tmp1 = a[i] > 0 ? 1 : -1;
		int tmp2 = last > 0 ? 1 : -1;
		if(tmp1 * tmp2 < 0)
		{
			res++;
			last = a[i];
		}
	}
	printf("%d\n", res);
}

int main()
{
	freopen("11039.in", "r", stdin);
	freopen("11039.out", "w", stdout);
	int t; scanf("%d", &t);
	while(t--) solve();
	return 0;
}

UVa 1339(LA 3213) —— Ancient Chipher

还是那句话,大白书上很多都没有翻译出来!!!

题目大一是在第二行中找到一种对应关系,然后交换一些顺序来得到第一行

即BAB 可以对应 CDD

我们可以容易发现,能够找到对应关系的、或者说是合法的对应关系一定是字母的个数都相同的

所以我们只需要统计个数就可以了

C++ AC Code (1A)

// By Jiangzh
#include <cstdio>
#include <cstring>

char a[200], b[200];
char cnt['z' + 10];

bool solve()
{
	int len = strlen(a);
	for(int i = 'A'; i <= 'Z'; ++i)
	{
		int tmp = 0;
		for(int j = 0; j < len; ++j) if(a[j] == i) ++tmp;
		++cnt[tmp]; tmp = 0;
		for(int j = 0; j < len; ++j) if(b[j] == i) ++tmp;
		--cnt[tmp];
	}
	for(int i = 1; i <= 100; ++i) if(cnt[i]) return 0;
	return 1;
}

int main()
{
	freopen("3213.in", "r", stdin);
	freopen("3213.out", "w", stdout);
	while(scanf("%s%s", b, a) == 2)
	{
		if(solve()) printf("YES\n");
		else printf("NO\n");
		memset(a, 0, sizeof(a));
		memset(b, 0, sizeof(b));
		memset(cnt, 0, sizeof(cnt));
	}
	return 0;
}


[130831]

UVa 1368(LA 3602) —— DNA Consensus String

注意理解题目,是自己找出一个序列来是总Hamming距离最小,而不是从已有的选择。

直接对每一位进行分许,选出出现次数做多的即可,如

AATT

AACC

TATC

那么对于第一位,出现了AAT,所以我们选择A;对于第二位,出现了AAA,所以选择A;对于第三位,出现了TCT,所以选择T;对于第四位,出现了TCC,所以选择C

所以最终答案为AATC

算距离有两种方法,一是得到了AATC后再带回去依次比较计算

二是在选择每一位字母的时候,如选择的那一位字母出现了X次,那么这一位的距离就为 N - X (N为总的个数 <题目里面是M,个人喜欢换成N> )

C++ AC Code (1A)

// By Jiangzh
#include <cstdio>
#include <cstring>
#include <algorithm>
const int N = 1000 + 10;

int n, m;
char a[N][N];
int cnt[N]['z'+10];
char ans[N];

void solve()
{
	scanf("%d%d", &n, &m);
	for(int i = 1; i <= n; ++i)
	{
		scanf("%s", a[i]);
		for(int j = 0; j < m; ++j)
		{
			++cnt[j][a[i][j]];
		}
	}
	int cal = 0;
	for(int j = 0; j < m; ++j)
	{
		int A = cnt[j]['A'];
		int C = cnt[j]['C'];
		int G = cnt[j]['G'];
		int T = cnt[j]['T'];
		int _max = std::max(std::max(A, G), std::max(C, T));
		if(_max == A) ans[j] = 'A';
		else if(_max == C) ans[j] = 'C';
		else if(_max == G) ans[j] = 'G';
		else if(_max == T) ans[j] = 'T';
		cal += (A + C + T + G) - _max;
	}
	printf("%s\n", ans);
	printf("%d\n", cal);
}

int main()
{
	freopen("3602.in", "r", stdin);
	//freopen("3602.out", "w", stdout);
	int t; scanf("%d", &t);
	while(t--)
	{
		solve();
		memset(a, 0, sizeof(a));
		memset(ans, 0, sizeof(ans));
		memset(cnt, 0, sizeof(cnt));
	}
	return 0;
}

UVa 10970 —— Big Chocolate

很简单的一道笔算题

C++ AC Code (1A)

// By Jiangzh
#include <cstdio>

int main()
{
	freopen("10970.in", "r", stdin);
	//freopen("10970.out", "w", stdout);
	long long n,m;
	while(scanf("%lld%lld", &n, &m) == 2)
		printf("%lld\n", n*m-1);
	return 0;
}


Uva 10340 —— All in All

扫描一次即可。我被Yes和No的大小写坑了……

C++ AC Code (2A)

// By Jiangzh
#include <cstdio>
#include <string>
#include <iostream>
using std::cin;
using std::string;

string s,t;

int main()
{
	freopen("10340.in", "r", stdin);
	//freopen("10340.out", "w", stdout);
	while(cin >> s >> t)
	{
		int lens = s.length(), lent = t.length();
		int i = 0, j = 0;
		bool flag = 0;
		while(i < lens && j < lent)
		{
			if(s[i] == t[j]) i++;
			j++;
			if(i == lens) flag = 1;
		}
		if(flag) printf("Yes\n");
		else printf("No\n");
	}
	return 0;
}

[130907]

UVa 10382 —— Watering Grass

经典的最小矩形覆盖问题,虽然是第一次做,但是应该很好想出贪心的方法

从左向右依次选择所能到达最右的并且能把前面覆盖完全的就可以了

注意浮点数的处理

C++ AC Code (2A)

// By Jiangzh
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
const int N = 10000 + 10;

int n, L, W;
struct Node{double L, R;} a[N];

bool cmp(const Node &a, const Node &b)
{
	if(a.L == b.L) return a.R > b.R;
	return a.L < b.L;
}

void read()
{
	int cnt = 0;
	for(int i = 1; i <= n; i++)
	{
		int p, r;
		scanf("%d%d", &p, &r);
		if(2 * r < W) continue;
		double leng = sqrt(1.0 * r * r - W * W / 4.0);
		a[++cnt] = (Node) {std::max(0.0,p-leng), std::min(L * 1.0,p+leng)};
	}
	n = cnt;
	std::sort(a+1, a+1+n, cmp);
}

int solve()
{
	if(a[1].L > 0) return -1;
	int now = 1, res = 1;
	double len = a[1].R;
	while(len < L && now < n)
	{
		int k = -1;
		for(int i = now+1; i <= n; i++)
		{
			if(a[i].L > a[now].R) break;
			if(k == -1 || a[i].R > a[k].R) k = i;
		}
		if(k == -1) return -1;
		len = a[k].R; now = k; res++;
	}
	if(len < L) return -1;
	return res;
}

int main()
{
	freopen("10382.in", "r", stdin);
	while(scanf("%d%d%d", &n, &L, &W) == 3)
	{
		memset(a, 0, sizeof(a));
		read();
		printf("%d\n", solve());
	}
	return 0;
}

UVa 10905 —— Children's Game

技巧性很强,不要简单地以为是字典序大的就在前面就会最优

利用sort,然后自己写一个比较函数,判断是a+b更优还是b+a更优即可(具体看代码)

C++ AC Code (1A)

// By Jiangzh
#include <cstdio>
#include <string>
#include <iostream>
#include <algorithm>
using std::string;
const int N = 50 + 10;

int n;
string s[N];

bool cmp(string a, string b)
{
	string tmp1 = a + b;
	string tmp2 = b + a;
	return tmp1 > tmp2;
}

int main()
{
	freopen("10905.in", "r", stdin);
	while(scanf("%d", &n) == 1 && n)
	{
		for(int i = 1; i <= n; i++) std::cin >> s[i];
		std::sort(s+1, s+1+n, cmp);
		for(int i = 1; i <= n; i++) std::cout << s[i];
		printf("\n");
	}
	return 0;
}



(http://blog.csdn.net/jiangzh7)

高三了,实在没时间了,以后再说吧…………………………………………………………


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值