第五届“传智杯”全国大学生计算机大赛(练习赛)前四题题解

第五届“传智杯”全国大学生计算机大赛(练习赛)

练习赛题单链接:传智杯练习赛

仅有会做的前四题题解,还是太弱了( ^ M ^ !!)

第一题

链接:复读
思路:
就是哈希表记录下出现了过的字符串,只要没出现过就加到答案里,不会哈希表的话也可以存到字符串数组里没回都遍历一遍也可以,因为数据量很小
代码:


#include
using namespace std;
map<string,int>cnt;
int idx;
int main()
{
	string s;
	string ans="";
	while(1)
	{
		cin>>s;
		if(s=="0") break;
		if(!cnt[s])
		{
			ans+=s;
			cnt[s]=1;
		}
	}
	cout<<ans<<endl;
	return 0;
}

第二题

链接:时钟
思路:
咋一看数据量很大,但算一下符合题目要求的时间排列一共才不到四十种,所以我们可以提前算出来所有符合条件的时间,然后对于给我们的分钟数我们也要处理下,因为它可能会超过24小时,这里就有0:00属于一开始0时0分呢 还是最后的24时0分呢 的问题,我们归结为属于24:00,然后一开始就将答案加一,让一开始的0:00不进入我们的考虑范围,然后24小时只有从0:12这个符合条件时间开始的到最后24:00的0:00,这样就好统计了
代码:


#include
using namespace std;
int x;
long long res[100];
int idx;
void judge(string s)
{
	bool f=false;
	int t=s[1]-s[0];
	for(int i=2;i<s.size();i++)
	{
		if(s[i]-s[i-1]!=t)
		{
			f=true;
			break;
		}
	}
	
	int n=s.size();
	int h=0,m=0;
	if(n==3)
	{
		h=stoi(s.substr(0,1));
		m=stoi(s.substr(1,2));
	}
	else 
	{
		h=stoi(s.substr(0,2));
		m=stoi(s.substr(2,2));
	}
	if(!f)
	{
		int x=h*60+m;
		res[++idx]=x;
	}
}
int solve()
{
	for(int i=0;i<24;i++)
	{
		for(int j=0;j<60;j++)
		{
			string s;
		    s+=to_string(i);
			if(j<10)
			{
			s.push_back('0');	
			}
			s+=to_string(j);
			judge(s);
		}
		
	}
	res[++idx]=24*60;//把最后的24:00加进去
}
int main()
{
	solve();
	cin>>x;
	int ans=1;
	int t=idx-1;//24小时中符合的时间数,减一是因为一开始的0:00不算,我们把24:00当作0:00算进去了已经
	if(x>(24*60))//这是算下有多少个24小时循环
	{
		int p=x/(24*60);
		ans+=p*t;
		x-=p*(24*60);
	}
	for(int i=2;i<=idx;i++)//从第二个开始,也就是一开始的0:00不算,从0:12开始计算剩下时间中有多少符合条件的
	{
		if(res[i]<=x)
		ans++;
		else
		break;
	}
	cout<<ans<<endl;

	return 0;
}

第三题

链接:平等的交易
思路:
我们首先就必须要用钱买一个物品,尽可能买最贵的,然后我们才能拿着这个贵的开始交换,然后当然是从最小的开始交换,直到自己物品价值不够了,因为我们一开始就是从价值最小的物品开始交换的所以这种策略交换的物品数是最多的,所以这道题我们排个序就行了
代码:


#include
using namespace std;
const int N=1e6+10;
int arr[N];
int n,w;
int main()
{
	cin>>n;
	for(int i=0;i<n;i++)
	{
		scanf("%d",&arr[i]);
	}
	cin>>w;
	sort(arr,arr+n);
	for(int i=n-1;i>=0;i--)
	{
		if(arr[i]<=w)
		{
			w=arr[i];
			break;
		}
	}
	int ans=0;
	for(int i=0;i<n;i++)
	{
		if(arr[i]<=w)
		{
			ans++;
			w-=arr[i];
		}
	}
	cout<<ans<<endl;
	return 0;
}

第四题

链接:清洁工
思路:
这道题就是个模拟,而且这个二维坐标我们需要一开始改变一下,因为我们往常建立的二维数组都是最上面的层数是最小的,但这是个坐标系,所以最下面的层数是最小的,所以我们的纵坐标要变化一下x=n+1-x,然后就是统计下每个位置什么时间被访问过就好了,而且这里我们压缩了一下二维,这样分别求商和取模就是所在的行和列。
代码:


#include
using namespace std;
const int N=600;
int arr[N][N];
vector<int>p[2600];
int n,m,x,y;
string s;
int fun(int x)
{
	int res=0;
	for(int i=1;i<=x;i++)
	{
		res+=i;
	}
	return res;
}
int main()
{
	cin>>n>>m>>y>>x;//先输入横坐标也就是先输入我们这里对应的列数,然后输入纵坐标也就是我们对应的行数,行数需要处理一下
	//看这个例子,一共五行,我们看下,以左上角为原点和以左下角为原点建立坐标系的数值的关系
	// 5        1
	// 4        2
	// 3        3
	// 2        4
	// 1        5
	//我们发现我们常用的左上角为原点的行数等于总行数+1-给出的行数
	//然后为什么xy都减一呢,是因为我们要压缩二维,所以要从0行0列开始到n-1行n-1列
	x=n+1-x;
	x--;
	y--;
	cin>>s;
	
	for(int i=0;i<s.size();i++)
	{
		if(s[i]=='N')//shang
		{
		p[x*n+y].push_back(i+1);
		x-=1;
		}
		else if(s[i]=='S')//xia
		{
		p[x*n+y].push_back(i+1);	
		x+=1;
		}
		else if(s[i]=='W')//zuo
		{
		p[x*n+y].push_back(i+1);	
		y-=1;	
		}
		else if(s[i]=='E')//you
		{
		p[x*n+y].push_back(i+1);
		y+=1;		
		}
	}
	for(int i=0;i<n*n;i++)
	//这里自己可以举例子看下,这个做法是可以算出来的,就是存一下每个点的访问时间,不管有没有访问,最后都存一下m+1方便我们统一计算,就是算相邻访问时间点的差值,所以一开始初始话一个t=0来算到第一次访问落的灰,然后更新t=这个时间点,一直算到最后m+1时刻,就算完了
	{
			p[i].push_back(m+1);
			int t=0;
			for(int j=0;j<p[i].size();j++)
			{
			arr[i/n][i%n]+=fun(p[i][j]-1-t);
			t=p[i][j];	
			}
			
	}
    	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++)
		{
			printf("%d ",arr[i][j]);
		}
		cout<<endl;
	}
	return 0;
}

你可能感兴趣的:(比赛题解,算法,数据结构)