(鲁东大学)1582. 【吴永辉】程序设计基础实践5-6(g-k)

【吴永辉】程序设计基础实践5-6(g-k)

*当前鲁东oj的J,K题数据有问题,提交请去原网站。

G. Ananagrams

Description
Most crossword puzzle fans are used to anagrams–groups of words with the same letters in different orders–for example OPTS, SPOT, STOP, POTS and POST. Some words however do not have this attribute, no matter how you rearrange their letters, you cannot form another word. Such words are called ananagrams, an example is QUIZ.

Obviously such definitions depend on the domain within which we are working; you might think that ATHENE is an ananagram, whereas any chemist would quickly produce ETHANE. One possible domain would be the entire English language, but this could lead to some problems. One could restrict the domain to, say, Music, in which case SCALE becomes a relative ananagram (LACES is not in the same domain) but NOTE is not since it can produce TONE.

Write a program that will read in the dictionary of a restricted domain and determine the relative ananagrams. Note that single letter words are, ipso facto, relative ananagrams since they cannot be ``rearranged’’ at all. The dictionary will contain no more than 1000 words.

Input
Input will consist of a series of lines. No line will be more than 80 characters long, but may contain any number of words. Words consist of up to 20 upper and/or lower case letters, and will not be broken across lines. Spaces may appear freely around words, and at least one space separates multiple words on the same line. Note that words that contain the same letters but of differing case are considered to be anagrams of each other, thus tIeD and EdiT are anagrams. The file will be terminated by a line consisting of a single #.

Output
Output will consist of a series of lines. Each line will consist of a single word that is a relative ananagram in the input dictionary. Words must be output in lexicographic (case-sensitive) order. There will always be at least one relative ananagram.

样例:
Input
ladder came tape soon leader acme RIDE lone Dreis peat
ScAlE orb eye Rides dealer NotE derail LaCeS drIed
noel dire Disk mace Rob dries

Output
Disk
NotE
derail
drIed
eye
ladder
soon

题目大意:
输入若干个字符串,以#结束。按照字典序输出字母组成独一无二的单词(如asd和sad算重复单词,asdd和bsdd则不算)

思路:
这道题简单的暴力就能解决。每个单词用桶来记录单词中每个字母的数量。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
struct words
{
	char w[21];
	ll le[26],f;
};
struct words2
{
	char x[21];
}pp[10000];//存唯一的单词
bool cmp(words2 a,words2 b)
{
	return strcmp(a.x,b.x)<0;
}
int main()
{
	struct words p[1000];
	ll t=0,tt=0;
	while(scanf("%s",p[t].w),p[t].w[0]!='#')
	{
		ll n=strlen(p[t].w);
		for(ll i=0;i<n;i++)
		{
			if(p[t].w[i]>='a'&&p[t].w[i]<='z')
				p[t].le[p[t].w[i]-'a']++;
			if(p[t].w[i]>='A'&&p[t].w[i]<='Z')
				p[t].le[p[t].w[i]-'A']++;
		}
		t++;
	}
	for(ll i=0;i<t;i++)
	{
		if(p[i].f)	continue; //当前单词并不唯一,直接跳过。
		ll flag1=0;//flag1记录当前单词是否唯一。
		for(ll j=i+1;j<t;j++)
		{
			ll flag2=0;//flag2表示是否有单词和当前单词重复。
			for(ll k=0;k<26;k++)
			{
				if(p[i].le[k]!=p[j].le[k])
				{
					flag2=1;
					break;
				}
			}
			if(!flag2)
			{
				p[i].f=p[j].f=1;
				flag1=1;
			}
		}
		if(!flag1)
			strcpy(pp[tt++].x,p[i].w);
	}
	sort(pp,pp+tt,cmp);
	for(ll i=0;i<tt;i++)
		cout<<pp[i].x<<endl;
}

H. The Spot Game

Description
The game of Spot is played on an N×N board as shown below for N=4. During the game, alternate players may either place a black counter (spot) in an empty square or remove one from the board, thus producing a variety of patterns. If a board pattern (or its rotation by 90 degrees or 180 degrees) is repeated during a game, the player producing that pattern loses and the other player wins. The game terminates in a draw after 2N moves if no duplicate pattern is produced before then.

Consider the following patterns:

If the first pattern had been produced earlier, then any of the following three patterns (plus one other not shown) would terminate the game, whereas the last one would not.

Input
Input will consist of a series of games, each consisting of the size of the board, N (2≤N≤50) followed, on separate lines, by 2N moves, whether they are all necessary or not. Each move will consist of the coordinates of a square (integers in the range 1…N) followed by a blank and a character +' or-’ indicating the addition or removal of a spot respectively. You may assume that all moves are legal, that is there will never be an attempt to place a spot on an occupied square, nor to remove a non-existent spot. Input will be terminated by a zero (0).

Output
Output will consist of one line for each game indicating which player won and on which move, or that the game ended in a draw.

样例:
Input
2
1 1 +
2 2 +
2 2 -
1 2 +
2
1 1 +
2 2 +
1 2 +
2 2 -
0
Output
Player 2 wins on move 3
Draw

大意:
两人在n*n的棋盘下棋,两人轮流操作,每轮各操作一次,每次可以在棋盘的空白处下一个棋子或者非空白出删除一个棋子。每次操作后的棋盘状态如果曾经出现过,那么对方获胜。(每次也包括棋盘向四个方向旋转后的状态)。如果操作结束无人获胜,输出Draw

思路:
每一次操作就用哈希把四个方向的棋盘状态全部记录一遍,存进数组前先遍历已有的棋盘状态和当前是否一致。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll ha=2077;
const ll mod=1e9+7;
ll a[10000];
ll ch[4][51][51]={0};
ll has(ll x,ll n)
{
	ll temp=0;
	for(ll i=1;i<=n;i++)
		for(ll j=1;j<=n;j++)
			temp=(temp+ch[x][i][j]*i*j)*ha%mod;
	return temp;
}
int main()
{
	ll n;
	while((cin>>n),n!=0)
	{
		memset(ch,0,sizeof(ch));
		ll x[101],y[101],t=0,ans1,ans2,temp,f=0;
		char z[101];
		for(ll i=1;i<=2*n;i++)
		{
			cin>>x[i]>>y[i]>>z[i];
			if(z[i]=='+')
			{
				ch[0][x[i]][y[i]]=1;
				temp=has(0,n);
				ch[0][x[i]][y[i]]=0;
			}
			if(z[i]=='-')
			{
				ch[0][x[i]][y[i]]=0;
				temp=has(0,n);
				ch[0][x[i]][y[i]]=1;
			}
			if(f==0)
				for(ll j=0;j<t;j++)
					if(a[j]==temp)
					{
						ans1=i%2+1;
						ans2=i;
						f=1;
						break;
					}
			if(z[i]=='+')
			{
				ch[0][x[i]][y[i]]=1;
				a[t++]=has(0,n);
				ch[1][y[i]][n+1-x[i]]=1;
				a[t++]=has(1,n);
				ch[2][n+1-y[i]][x[i]]=1;
				a[t++]=has(2,n);
				ch[3][n+1-x[i]][n+1-y[i]]=1;
				a[t++]=has(3,n);
			}
			if(z[i]=='-')
			{
				
				ch[0][x[i]][y[i]]=0;
				a[t++]=has(0,n);
				ch[1][y[i]][n+1-x[i]]=0;
				a[t++]=has(1,n);
				ch[2][n+1-y[i]][x[i]]=0;
				a[t++]=has(2,n);
				ch[3][n+1-x[i]][n+1-y[i]]=0;
				a[t++]=has(3,n);
			}
		}
		if(f)
			cout<<"Player "<<ans1<<" wins on move "<<ans2<<endl;
		else
			cout<<"Draw"<<endl;
	}
}

I. Conformity

Description
Frosh commencing their studies at Waterloo have diverse interests, as evidenced by their desire to take various combinations of courses from among those available.

University administrators are uncomfortable with this situation, and therefore wish to offer a conformity prize to frosh who choose one of the most popular combinations of courses. How many frosh will win the prize?

Input
The input consists of several test cases followed by a line containing 0. Each test case begins with an integer 1≤n≤10000, the number of frosh. For each frosh, a line follows containing the course numbers of five distinct courses selected by the frosh. Each course number is an integer between 100 and 499.

Output
The popularity of a combination is the number of frosh selecting exactly the same combination of courses. A combination of courses is considered most popular if no other combination has higher popularity. For each line of input, you should output a single line giving the total number of students taking some combination of courses that is most popular.

样例:
Input
3
100 101 102 103 488
100 200 300 101 102
103 102 101 488 100
3
200 202 204 206 208
123 234 345 456 321
100 200 300 400 444
0
Output
2
3

大意:
每组数据有n行,表示有n个学生。一行5个数字(每个数字均为三位数)表示每个学生选择的五个科目。任意五个数的组合受欢迎度为选择此组合的同学数,计算欢迎度最高的组合(可能有多个)的欢迎度总和。

思路:
因为一行5个数字且每个数字均为三位数,所以可以把每一行压缩成一个数字(long long),也可以用哈希(本人用的哈希,刚学会所以想练一练)。把结果存到map里去,遍历两遍map,第一遍找出最高的欢迎度,第二遍把最高欢迎度的组合的欢迎度相加。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const ll p=2077;
ll ha(ll a[])
{
	ll temp=0;
	for(ll i=0;i<5;i++)
		temp=(temp+a[i])*p%mod;
	return temp;
}
int main()
{
	ll n;
	map<ll, ll> M;
	while((cin>>n),n)
	{
		ll has[10001]={0},a[5],sum=0,temp,ma=0;
		for(ll i=0;i<n;i++)
		{
			for(ll j=0;j<5;j++)
				cin>>a[j];
			sort(a,a+5);
			M[ha(a)]++;
		}
		map<ll, ll>::iterator iter; 
		for(iter=M.begin();iter!=M.end();iter++)
			if(iter->second>ma)
				ma=iter->second;
		for(iter=M.begin();iter!=M.end();iter++)
			if(iter->second==ma)
				sum+=ma;
		cout<<sum<<endl;
		M.erase(M.begin(),M.end());		
	}
}

J. Broken Keyboard(UVA11988)

Description
You’re typing a long text with a broken keyboard. Well it’s not so badly broken. The only problem with the keyboard is that sometimes the “home” key or the “end” key gets automatically pressed (internally).

You’re not aware of this issue, since you’re focusing on the text and did not even turn on the monitor! After you finished typing, you can see a text on the screen (if you turn on the monitor).

In Chinese, we can call it Beiju. Your task is to find the Beiju text.

Input
There are several test cases. Each test case is a single line containing at least one and at most 100,000 letters, underscores and two special characters ‘[’ and ‘]’. ‘[’ means the “Home” key is pressed internally, and ‘]’ means the “End” key is pressed internally. The input is terminated by end-of-file (EOF).

Output
For each case, print the Beiju text on the screen.

样例:
Input
This_is_a_[Beiju]_text
[[]][][]Happy_Birthday_to_Tsinghua_University
Output
BeijuThis_is_a__text
Happy_Birthday_to_Tsinghua_University

大意:
每组数据一行,表示敲下的键盘(’[‘表示光标移到文本的最前端,’]'表示光标移到文本的最后端),输出真实的文本。

思路:
如果不用deque,将很难处理这种问题(用数组模拟链表……),而用deque就会变得很容易理解。扫一遍整一行,连在一起的字符合并,遇到‘【】’就根据上一个光标移动符号判断当前合并的字符放在队列的前段或后端。

代码:

#include<bits/stdc++.h>
using namespace std;
deque<string> d;
int main()
{
	string temp,str;
	while(cin>>str)
	{
		int n=str.size();
		char flag=']';
		for(int i=0;i<n;i++)
		{
			if(str[i]=='['||str[i]==']')
			{
				if(flag=='[')	d.push_front(temp);
				if(flag==']')	d.push_back(temp);
				flag=str[i];
				temp.clear();
			}
			else
			temp+=str[i];
		}
		if(str[n-1]!='['&&str[n-1]!=']')
		{
			if(flag=='[')	d.push_front(temp);
			if(flag==']')	d.push_back(temp);
			temp.clear();
		}
		while(!d.empty())
		{
			cout<<d.front();
			d.pop_front();
		}
		cout<<endl;
	}
}

K. Concatenation of Languages(UVA10887)

Description
A language is a set of strings. And the concatenation of two languages is the set of all strings that are formed by concatenating the strings of the second language at the end of the strings of the first language.

For example, if we have two language A and B such that:

A= {cat, dog, mouse}

B= {rat, bat}

The concatenation of A and B would be:

C= {catrat, catbat, dograt, dogbat, mouserat, mousebat}

Given two languages your task is only to count the number of strings in the concatenation of the two languages.

Input
There can be multiple test cases. The first line of the input file contains the number of test cases, T (1≤T≤25). Then T test cases follow. The first line of each test case contains two integers, M and N (M,N<1500), the number of strings in each of the languages. Then the next M lines contain the strings of the first language. The N following lines give you the strings of the second language. You can assume that the strings are formed by lower case letters (‘a’ to ‘z’) only, that they are less than 10 characters long and that each string is presented in one line without any leading or trailing spaces. The strings in the input languages may not be sorted and there will be no duplicate string.

Output
For each of the test cases you need to print one line of output. The output for each test case starts with the serial number of the test case, followed by the number of strings in the concatenation of the second language after the first language.

Samples
Input
2
3 2
cat
dog
mouse
rat
bat
1 1
abc
cab
Output
Case 1: 6
Case 2: 1

大意:
有AB两组,每组有若干单词,问AB两组各抽出一个单词有多少种组合。(A组在B组前面)

思路:
用map构建桶,遍历所有的单词组合,放入桶中,输出寄存器的数量。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const ll ha=2077;
char x[1500][26],y[1500][26];
int main()
{
	map<string,ll> M;
	ll n,t=1;
	cin>>n;
	while(n--)
	{
		ll a,b;
		string temp;
		cin>>a>>b;
		getchar();
		for(ll i=0;i<a;i++)
			gets(x[i]);
		for(ll i=0;i<b;i++)
			gets(y[i]);
		for(ll i=0;i<a;i++)
			for(ll j=0;j<b;j++)
			{
				temp+=x[i];
				temp+=y[j];
				M[temp]++;
				temp.clear();
			}
		//map<string,ll>::iterator iter; 
		cout<<"Case "<<t++<<": "<<M.size()<<endl;
		M.erase(M.begin(),M.end());
	}
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值