XUPT2018—ACM第一次个人赛题解

A - Patrick去购物        CodeForces - 599A

 

今天 Patrick 等待着他的朋友 Spongebob 来他家玩。为了迎接 Spongebob,Patrick 需要去他家附近的两家商店  买一些吃的。他家离第一家商店有d1米远,离第二家商店有d2米远。还有,两家商店之间的距离是d3,帮Patrick计算去两家商店然后回家的最短距离。

Patrick 永远从他家出发,他不介意重复经过同一个地点或者同一条路,唯一的目标就是:最小化经过两间商店然后回家的距离。      

Input

第一行的输入包括三个整数 d1d2d3 (1 ≤ d1, d2, d3 ≤ 108)

  • d1 是 Patrick 的家离第一间商店的距离;
  • d2 是 Patrick 的家离第二 间商店的距离;
  • d3 是两间商店的距离 .
Output

输出经过两家商店然后回家的最短距离。

Sample Input
10    20    30
1     1     5
		
Sample Output
60
4
Hint

第一个样例是先经过第一间,再经过第二间,再回家    


题意:从家出发经过两个超市再回家的最短距离,其实有4种可能一开始没想明白。第一就是绕一圈,第二就是先去一个超市然后回来再去另一个超市再回来,第三先去A超市再去B超市,再回B超市再回家,第四先去B再去A。
#include <cstdio>
#include <iostream>
#include <algorithm>
typedef long long ll;
using namespace std;
ll d1,d2,d3,ans;

int main()
{
	while(cin >> d1 >> d2 >> d3)
	{
		ans=min(2*(d1+d2),d1+d2+d3); 
		ans=min(ans,2*(d1+d3));
		ans=min(ans,2*(d2+d3));
		cout << ans << endl;
	}
	return 0;
}

B - Pasha的木棒        CodeForces - 610A 

Pasha有一根长度为n的大棒, 他想切三刀从而获得四根小棒。每一根小棒的长度必须是正数且加起来的和为n。

Pasha喜欢矩形但是不喜欢正方形,所以他想,有多少种切法能让切出来的四根小棒通过端点连接端点的方式连接后,能够组成一个矩形但是不能组成一个正方形。   

你的任务是帮助Pasha去计算有多少种方法。

两种方法是不同的,当且仅当存在一个数x,在两种方法中,x长度的小棒的数目是不同的。      

Input

第一行输入包括一个正整数n (1 ≤ n ≤ 2·109)  Pasha的大棒的长度  

Output

输出包括一个数字 -- 将Pasha的大棒切成4根小棒,这四根小棒通过端点连接端点的方式连接后,只能组成矩形不能组成正方形的切割方式的数目。  

Sample Input
6
20
 
Sample Output

1

4


Hint

第一个样例的唯一切割方法是  {1, 1, 2, 2}.

第二个样例的切割方法有4种: {1, 1, 9, 9}, {2, 2, 8, 8}, {3, 3, 7, 7} and {4, 4, 6, 6}.

请注意,{5, 5, 5, 5} 是不行的。

   

题意:一个数分成四个数,然后形成矩形(不能是正方形),先看是不是偶数,奇数直接输出0,偶数直接除以4,如果发现是可以组成正方形的就减一。


#include <iostream>
#include <algorithm>
typedef long long ll;
using namespace std;
ll n,ans;

int main()
{
	while(cin >> n)
	{
		ans=n/4;
		if (n%4==0) ans--;
		if (n%2) cout << "0" << endl;
		else cout << ans << endl;
	}
	return 0;
}

C - Limak存糖果        CodeForces - 611A 


今天是星期三,一周中的第三天,明天就是2015年的最后一天。

Limak是一只小熊,它很期待2016年。

Limak靠吃糖维生,为了证明自己是有多么努力的活下去,他决定在2016年一整年中,定期的存一些糖。它考虑过很多种存糖方案,它可以在一周的某一天或者一个月的某一天存一颗糖。         

Limak决定从两种方案中选择一种,但是他不知道按照这种方式,他会在2016年一整年存多少糖。请你计算后告诉它。 

Input

唯一一行输入会以下面两种方式输入  

  • "x of week" -- x (1 ≤ x ≤ 7) 表示一周中的第x天。规定一周中第一天是星期一,第七天是星期天。  
  • "x of month" -- x (1 ≤ x ≤ 31) 表示一个月中的第x天。  
Output

输出Limak在2016结束后会存多少糖

Sample Input
4 of week
 
30 of month
 
Sample Output

52

11

Hint

Limak的日历是公历。于是你也要按照公历来计算。星期一是一个星期的开始。   

可以从电脑自带的日历看到2016年的公历。

第一个样例中Limak会在每个星期四存一颗糖,2016年一共有52个星期四,所以Limak在2016年会存52颗糖。  

第二个样例中Limak会在每个月的30号存下一颗糖,2016年一共有11个30号,所以Limak在2016年会存11颗糖。    


题意:非常的暴力,先分月还是周,然后再分第几天,然后直接得出结果。

#include <cstdio>
#include <iostream>
#include <string>
using namespace std;
string s1,s2;
int n,ans;

int main()
{
	while(cin >> n >> s1 >> s2)
	{
		if (s2=="week")
		{
			if (n==5||n==6) ans=53;
			else ans=52;
		}
		else
		{
			if (n<=29) ans=12;
			else if (n==30) ans=11;
			else if (n==31) ans=7;
		}
		cout << ans << endl;
	}
	return 0;
}

D - 美丽的油画        CodeForces - 651B 


从很久很久以前,那里有一个画展,画展有n幅画,第i幅画有一个美丽指数ai。我们知道的是,一个当游览者从一张画到一张美丽指数更高的画的时候,会变得开心。

画将会一列的排放,我们可以随意安排画的顺序。那么如果游览者以从头到尾的顺序游览的画,总共最多可以变开心多少次呢。

换而言之,我们需要将美丽指数重新排列,使得有最多的i (1 ≤ i ≤ n - 1), 符合 ai + 1 > ai. 输出符合条件的i的数目。      

Input

第一行输入一个整数n (1 ≤ n ≤ 1000) -- 画的数目

第二行输入一串整数序列 a1, a2, ..., an (1 ≤ ai ≤ 1000) -- ai 表示第i张画的美丽指数。

 

Output

输出一个整数 - 排序后,使得满足ai + 1 > ai 的i最多的数目

Sample Input
5
20 30 10 50 40
 
4
200 100 100 200
 
		
Sample Output
4
2
Hint

在第一个样例中,排序后的序列是:10,20,30,40,50

在第二个样例中,排序后的序列是:100,200,100,200


题意:排序,然后求所有递增序列的长度-1。
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
int n,a[1005],t,ans;

int main()
{
	while(cin >> n)
	{
		ans=0;
		for (int i=0;i<n;i++)
			scanf("%d",&a[i]);
		sort(a,a+n);
		for (int i=0;i<n;i++)
		{
			if (a[i]) t=a[i];
			else continue;
			for (int j=i+1;j<n;j++)
			{
				if (a[j]>t)
				{
					t=a[j];
					a[j]=0; //走过的地方置0
					ans++;
				}
			}
		}
		cout << ans << endl;
	}
	return 0;
}

E - N皇后问题        HDU - 2553 


在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上。 
你的任务是,对于给定的N,求出有多少种合法的放置方法。 

Input共有若干行,每行一个正整数N≤10,表示棋盘和皇后的数量;如果N=0,表示结束。Output共有若干行,每行一个正整数,表示对应输入行的皇后的不同放置数量。Sample Input
1
8
5
0
Sample Output
1
92
10

题意:明显的dfs(比赛时写的有点乱),然后数据比较小直接算出结果打表,不容易超时。

#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstring>
using namespace std;
int vis[15],pre[15],n,cnt;
int ans[15]={0,1,0,0,2,10,4,40,92,352,724};

void dfs(int x)
{
	if (x==n) 
	{
		cnt++;
		return;
	}
	for (int j=0;j<n;j++)
	{
		if (!vis[j])
		{
			int flag=1;
			for (int i=0;i<x;i++)
			{
				if (abs(x-i)==abs(j-pre[i]))
				{
					flag=0;
					break;
				}
			}
			if (!flag) continue;
			pre[x]=j;
			vis[j]=1;
			dfs(x+1);
			vis[j]=0;
		}
	}
}
int main()
{
	while(cin >> n && n)
	{
		/*
		memset(vis,0,sizeof(vis));
		cnt=0;
		for (int i=0;i<n;i++)
		{
			pre[0]=i;
			vis[i]=1;
			dfs(1);
			vis[i]=0;
		}
		*/   //dfs的过程
		cout << ans[n] << endl;
	}	
	return 0;
}

F - 车辆排序        CodeForces - 606C 


一个无限长的铁路有一个载着n辆车的火车,每一辆车的编号从1到n。每一辆车的编号都是不同的。他们的顺序是无序的。

David Blaine想要将这些车按照他们的编号从小到大排序,他可以做两种操作。第一种,他可以将一辆车从任意位置移动到所有车的第一位。第二种,他可以将一辆车从任意位置移动到所有车的最后一位。

不过他很懒,所以他想知道将这些车排好序最少做几次操作就可以。      

Input

第一行输入包含一个整数n (1 ≤ n ≤ 100 000) -- 车的数目

第二行包含n个整数 pi (1 ≤ pi ≤ npi ≠ pj if i ≠ j) - 车的编号的初始序列      

Output

输出一个整数 - 将车辆排好序的最小操作次数

Sample Input
5
4 1 2 5 3
 
4
4 1 3 2
 
Sample Output

2

2

Hint

在第一个样例中,将编号为4的车放到最后,然后把编号为5的车放到最后就可以了。总共是2次操作。
 


题意:比赛时没写出来,以为是最长上升子序列,只会n^2,然后超时,比赛后发现是这个上升子序列序号要连续,看了大神的代码写出来。

#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
int a[100005];
int n,x;

int main()
{
	while(cin >> n)
	{
		memset(a,0,sizeof(a));
		int maxl=0;
		for (int i=0;i<n;i++)
		{
			scanf("%d",&x);
			a[x]=a[x-1]+1; //在自己小1的数的长度上加一就是到现在以x结尾的最长长度
			if (a[x]>maxl) maxl=a[x]; //最长的长度
		}
		cout << min(n,n-maxl) << endl;	
	}
	return 0;
}

G - 生理周期        POJ - 1006


人生来就有三个生理周期,分别为体力、感情和智力周期,它们的周期长度为23天、28天和33天。每一个周期中有一天是高峰。在高峰这天,人会在相应的方面表现出色。例如,智力周期的高峰,人会思维敏捷,精力容易高度集中。因为三个周期的周长不同,所以通常三个周期的高峰不会落在同一天。对于每个人,我们想知道何时三个高峰落在同一天。对于每个周期,我们会给出从当前年份的第一天开始,到出现高峰的天数(不一定是第一次高峰出现的时间)。你的任务是给定一个从当年第一天开始数的天数,输出从给定时间开始(不包括给定时间)下一次三个高峰落在同一天的时间(距给定时间的天数)。例如:给定时间为10,下次出现三个高峰同天的时间是12,则输出2(注意这里不是3)。Input输入四个整数:p, e, i和d。 p, e, i分别表示体力、情感和智力高峰出现的时间(时间从当年的第一天开始计算)。d 是给定的时间,可能小于p, e, 或 i。 所有给定时间是非负的并且小于365, 所求的时间小于21252。  

当p = e = i = d = -1时,输入数据结束。Output从给定时间起,下一次三个高峰同天的时间(距离给定时间的天数)。  

采用以下格式:  
Case 1: the next triple peak occurs in 1234 days.  

注意:即使结果是1天,也使用复数形式“days”。Sample Input
0 0 0 0
0 0 0 100
5 20 34 325
4 5 6 7
283 102 23 320
203 301 203 40
-1 -1 -1 -1
Sample Output
Case 1: the next triple peak occurs in 21252 days.
Case 2: the next triple peak occurs in 21152 days.
Case 3: the next triple peak occurs in 19575 days.
Case 4: the next triple peak occurs in 16994 days.
Case 5: the next triple peak occurs in 8910 days.
Case 6: the next triple peak occurs in 10789 days.
Hint

Translator

北京大学程序设计实习2007, Xie Di

题意:这题很难理解,看了20多分钟题目,终于看懂了,简单的说就是算天数,然后使天数加上开始的天数在减去各个高峰开始的天数满足高峰的周期,一开始以为是不是要二分,后来发现直接暴力即可。
#include <cstdio>
#include <iostream>
using namespace std;
int p,e,i,d,ans,cnt=0;
int main()
{
	while(cin >> p >> e >> i >> d)
	{
		if (p==-1&&e==-1&&i==-1&&d==-1)
			break;
		ans=0;
		for (int j=1;j<=21252;j++)
		{
			if ((j+d-p)%23==0&&(j+d-e)%28==0&&(j+d-i)%33==0) //暴力一天一天试,看满足条件不。
			{
				ans=j;
				break;
			}
		}
		printf("Case %d: the next triple peak occurs in %d days.\n",++cnt,ans);
	}
	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值