UCF Local Programming Contest 2018题解

UCF Local Programming Contest 2018

A Window on the Wall

添加链接描述

思路

直接判断墙的长和宽是否均长于 2 倍的 d,因为两边均要留有空隙窗户的最大面积为
(w-2d)(h-2*d)

参考代码:

#include<bits/stdc++.h>
using namespace std;
int w,h,d;
int main(){
 	cin>>w>>h>>d;
 	if(w>2*d&&h>2*d)
		 printf("%d\n",(w-2*d)*(h-2*d));
	 else puts("0");
	 return 0;
}

B SGA President

添加链接描述

题意:

给定一个整数 n,后面紧接着 n 个字符串,代表着名字。
要求:字符串首字母相等,而两字符串不相等则为一种成功组合。问最多有多少组合。
其中 abc/acc 是一种成功组合,acc/abc 也是一种成功组合。

思路:

先排序是必须的,然后遍历一遍即可。
在相同的首字母中遍历,如果下一个与上一个不相同,则 ans+遍历的长度
若相同则 ans+上一次遍历的长度

参考代码:

#include<iostream>
#include<cstring>
#include<algorithm>
#include<string>
using namespace std;
typedef long long ll;
bool cmp(string x,string y){
 return x<y;
}
string str[100010];
int main(){
 	ll n,ans=0;
 	cin>>n;
	 for (int i=1;i<=n;i++) cin>>str[i];
 		sort(str+1,str+n+1,cmp);
	 int l=1,r=1;
	 char tmp=str[1][0];
 	for (int i=2;i<=n;i++){
		 if (str[i][0]!=tmp){
 			tmp=str[i][0];
 			l=r=1;
 			continue;
		 }
	 	if (str[i]!=str[i-1]){
			 r=0;
 			}
 		ans+=2*(l-r);
 		l++; r++;
		 }
	 	cout<<ans<<endl;
	 return 0;
}

C First Last Sorting

添加链接描述

思路

正难则反,我们可以先求出最多有多少个数字不需要移动就可以完成排序,至于怎么求,我
们可以发现那些严格递增子序列可以就不要移动,就比如样例:8, 3, 6, 7, 4, 1, 5, 2 。其中
3,4,5 可以不需要移动,所以我们需要找到最长严格递增的子序列。首先第一状态 dp【i】,
为以 i 结尾的严格递增的子序列,那么 dp【i】=dp【i-1】+1。找到最大的 dp 值,最后序列
长度 n-dp【i】就是答案了。

参考代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
int dp[maxn];
int a[maxn];
int main(){
     int n,m;
	 int ans=0;
	 scanf("%d",&n);
	 memset(dp,0,sizeof(dp));
	 for(int i=1;i<=n;i++){
		 scanf("%d",&m);
		 dp[m]=dp[m-1]+1;
		 ans=max(dp[m],ans);
	 }
 	printf("%d\n",n-ans);
 	return 0;
}

D Rounding Many Ways

添加链接描述

思路

本题的关键是 XY=10^Z,XW=N,由于第一个式子的,我们可以得到 X 一定是 2,5 的乘积,所以我们先对 N 质数分解,记录 2,5 的个数,最后只要把这些 2,5 组合一下就可以了。

参考代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
vector<ll> vec;
ll qpow(ll n,ll m){
	 ll ans=1;
	 while(m){
		 if(m&1)ans=ans*n;
			 n=n*n;
			 m/=2;
	 }
	 return ans;
}
int main(){
	 ll n;
	 scanf("%lld",&n);
	 ll num1,num2;
	 num2=num1=0;
	 while(n%2==0&&n!=0){
		 n/=2;
		 num1++;
 // cout<<n<<endl;
	 }
	 while(n%5==0&&n!=0){
		 n/=5;
 		num2++;
      // cout<<n<<endl;
	 }
// cout<<num1<<" "<<num2<<endl;
 	for(int i=0;i<=num1;i++){
 		ll tem1=qpow(2,i);
	 	for(int j=0;j<=num2;j++){
 //tem1=tem1*qpow(5,j);
 			vec.push_back(tem1*qpow(5,j));
		 }
 	}
 	sort(vec.begin(),vec.end());
	 int ans1=vec.size();
	 printf("%d\n",ans1);
 	for(int i=0;i<ans1;i++){
		 printf("%lld\n",vec[i]);
	 }
 return 0;
} 

E Cupcake Bonuses

添加链接描述

思路

本题是一道模拟题。我们可以定义数组 ans【i】记录员工已经得到的工资,base 数组记录
multiplier,最后定义 n 个 vertor,用来存某个员工的下属,当进行操作 1 时直接把下属的编
号放进相应的 vector,进行操作二时更新 base 数组,进行操作三时,更新当前员工及其下
属的 ans,更新的话写一个 dfs 就行了,当进行操作四是直接输出相应的 ans 就好了。

参考代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+5;
ll base[maxn];
ll ans[maxn];
vector<int> vec[maxn];
void dfs(int now,ll val){
 int len=vec[now].size();
 ans[now]+=base[now]*val;
 for(int i=0;i<len;i++){
 //ans[vec[now][i]]+=base[vec[now][i]]*val;
	 dfs(vec[now][i],val);
	 }
}
int main(){
 	int n;
	 ll s;
    int num;
	 num=1;
	 scanf("%d%lld",&n,&s);
	 for(int i=0;i<maxn;i++)base[i]=s;
		 memset(ans,0,sizeof(ans));
	 while(n--){
 		 ll val;
		 int id,op;
		 scanf("%d",&op);
		 if(op==1){
			 scanf("%d",&id);
			 num++;
			 vec[id].push_back(num);
		 }
		 else if(op==2){
			 scanf("%d%lld",&id,&val);
			 base[id]=val;
		 }
		 else if(op==3){
 			scanf("%d%lld",&id,&val);
			 dfs(id,val);
		 }
		 else{
 			scanf("%d",&id);
		    printf("%lld\n",ans[id]);
		 }
	 }
 return 0;
}

F Team Shirts/Jerseys

添加链接描述

题意:

给定一个整数 m,长度小于 10。再给出一个整数 n,后面紧接着 n 个整数,同时允
许一个数 x,x 可以选 1 到 99 的数字,总共 n+1 个整数。
问是否存在将 n+1 个整数随意选出某些数,可以拼凑成 m,这里 033 与 33 不相等,即拼凑
成的数要完全等于 m。若能输出 1,不能则输出 0。

思路:

m 的长度小,直接搜索。
记得处理几种特殊情况,首字符为 0 的时候,必不能实现拼凑。然后有种特殊情况是可
以任意选择一个数(1 到 99),为了处理这种情况可以每次搜索都走两次,一次是取 1~9 的,
另外一次是取 10~99,详情看代码。

参考代码:

#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll;
ll str;
ll n,len,a[20],b[30],c[30];
void init(){
 scanf("%lld%lld",&str,&n);
 	ll tmp=str;
	 len=0;
	 while (tmp){
		 len++;
		 tmp/=10;
	 }
	 for (ll i=len-1;i>=0;i--){
 		a[i]=str%10;
		 str/=10;
	 }
	 for (ll i=0;i<n;i++){
 		scanf("%lld",&tmp);
		 b[i]=tmp/10;
		 c[i]=tmp%10;
	 }
}
ll bfs(ll pos,ll flag,ll vis[]){
 	if (pos==len) return 1;
	 if (pos>len||a[pos]==0) return 0;
 	if (flag==0&&(bfs(pos+1,1,vis)||bfs(pos+2,1,vis))) return 1; //处理任选情况
	 for (ll j=0;j<n;j++){
		 if(!vis[j]){
		 ll t=0;
 		for (ll k=0;k<j;k++){ //剪枝
 			if (!vis[k]&&c[j]==c[k]&&b[j]==b[k]){
			 t=1;
			 break;
	 }
 }
	 if (t) continue;
		 if (b[j]==0){
 		if (c[j]==a[pos]){
			 vis[j]=1;
		 if (bfs(pos+1,flag,vis)) return 1;
 			vis[j]=0;
		 }
     }
 		else if(pos+1<len){
		 if (b[j]==a[pos]&&c[j]==a[pos+1]){
			 vis[j]=1;
		 if (bfs(pos+2,flag,vis)) return 1;
		 vis[j]=0;
		 }
	 }
	 }
 }
	 return 0;
}
int main(){
 	init();
 	ll vis[30];
	 memset(vis,0,sizeof(vis));
	 printf("%lld\n",bfs(0,0,vis));
	 return 0;
}

G Parity of Strings

添加链接描述

思路

直接模拟判断字符串中每个字符出现的次数
如果均是偶数次输出 0
如果均是奇数次输出 1
如果均有则输出 2

参考代码:

#include<bits/stdc++.h>
using namespace std;
char s[75];
int cnt[30];
int main() {
 scanf("%s",s);
 int len=strlen(s);
 for(int i=0;i<len;i++)
  	 cnt[s[i]-'a']++;
 	int flageven=0,flagodd=0;
	 for(int i=0;i<26;i++){
		 if(cnt[i]>0&&cnt[i]%2==0)flageven=1;
		 if(cnt[i]%2==1) flagodd=1;
	 }
 if (flageven&&flagodd) printf("2\n");
 	 else if(flageven) printf("0\n");
   		 else printf("1\n");
 return 0;
}

H Historical TV Remote Control

添加链接描述

思路

简单贪心
楼层的范围是 1 到 999,直接判断每个楼层是否可达,
假如该楼层中包含损坏的数字则不可达,否则可达,注意特判 0 层的情况
若该楼层可达且比当前答案值更小,则更新答案

参考代码:

#include<bits/stdc++.h>
using namespace std;
int n,broken[10],target;
bool check(int x){
  	if(x==0&&broken[0]) return false;
 	while(x){
	 int pos=x%10;
	 if(broken[pos]) return false;
	 x/=10;
 }
	 return true;
}
int main(){
 	cin>>n;
 	for(int i=0;i<n;i++){
 		int x;
 		cin>>x;
	    broken[x]=1;
 }
  cin>>target;
	 int ans=1000;
 	 for(int i=0;i<=999;i++){
	 if(check(i))
  ans=min(ans,abs(i-target));
 }
 cout<<ans<<endl;
 return 0;
}

I Chocolate Gifts

添加链接描述

题意:

给出 w,h 和 x,礼物盒的规格是(wh),x 是巧克力的总面积值。
要求做出最多的巧克力数目。其中做出的巧克力可以放入礼物盒
,并且每种巧克力规格都不同(规格 a
b 与规格 ba 视作不一样),若盒子
规格是 a
b(a!=b),那么能放下 ab 的巧克力,而不能放下 ba 的巧克力。

思路:

比较出 w,h 的最小值,设 w 更小。判定盒子能否装入 w*w 规格的巧克力。

  1. 二分
  2. 注意精度

参考代码:

#include <stdio.h>
#include <stdlib.h>
typedef struct Pair {
 long long area;
 long long count;
} Pair;
 long long getMin(long long a, long long b) {
 return a < b ? a : b;
}
// Returns the sum of all integers in the range [a, b]
long long sumRange(long long a, long long b) {
  if (b < a) {
   return 0;
 }
 long long len = b - a + 1;
 return (a - 1) * len + len * (len + 1) / 2;
}
// Returns the sum (as a double) of all integers in the range [a, b]
double sumRangeDouble(double a, double b) {
 if (b < a) {
 return 0;
 }
 double len = b - a + 1;
 return (a - 1) * len + len * (len + 1) / 2;
}
// Returns a pair of total area and number of unique bars that can bemade
// with each bar having area at most maxSize and fitting into a boxof size w x h
Pair calc(long long w, long long h, long long maxSize) {
	  Pair p;
	 double dArea = 0.0;
	 double dCount = 0.0;
	 long long MAX_X = 1000000;
 // Do everything with doubles first to skip cases that overflow
 for (long long x = 1; x <= w && x <= MAX_X; x++) {
	 if (maxSize / x == 0) break;
	 if (x * x > maxSize) break;
	 // x < y
	 {
		 long long minY = x + 1;
		 long long maxY = getMin(h, maxSize / x);
 if (minY <= maxY) {
	 dCount += maxY - minY + 1;
	 dArea += x * sumRangeDouble(minY, maxY);
	 }
 }
 // y <= x
 {
 long long minY = x;
 long long maxY = getMin(w, maxSize / x);
 if (minY <= maxY) {
	 dCount += maxY - minY + 1;
	 dArea += x * sumRangeDouble(minY, maxY);
		 }
	 }
 }
 if (dArea >= 1.1e18) {
	 p.area = 1100000000000000000LL;
	 p.count = 0;
	 return p;
 }

 p.area = 0;
 p.count = 0;
 for (long long x = 1; x <= w && x <= MAX_X; x++) {
	 if (maxSize / x == 0) break;
		 if (x * x > maxSize) break;
	 // x < y
 {
		 long minY = x + 1;
		 long maxY = getMin(h, maxSize / x);
		 if (minY <= maxY) {
			 p.count += maxY - minY + 1;
			 p.area += x * sumRange(minY, maxY);
			 }
	 }
 // y <= x
 {
 long minY = x;
 long maxY = getMin(w, maxSize / x);
	 if (minY <= maxY) {
		 p.count += maxY - minY + 1;
		 p.area += x * sumRange(minY, maxY);
		 }
	 }
 }
 return p;
}
int main(void) {
	 long long w, h, x;
 scanf("%lld %lld %lld", &w, &h, &x);
	 if (w > h) {
	 long long tmp = w;
	 w = h;
	 h = tmp;
	 }
 long long min = 1;
 long long max = 2000000000LL;
 while (min < max) {
	 long long mid = (min + max + 1) / 2;
	 Pair p = calc(w, h, mid);
 if (p.area > x) {
	 max = mid - 1;
 } 
 else {
	 min = mid;
 	 }
 }
	 Pair p = calc(w, h, min);
   	 Pair p2 = calc(w, h, min + 1);
	 long long possibleExtra = p2.count - p.count;
	 long long ans = p.count + getMin(possibleExtra, (x - p.area) /
	(min + 1));
 printf("%lld\n", ans);

 return 0;
}

J Circle Meets Square

添加链接描述

思路

判断正方形与圆是否相交
(1)正方形与圆有面积交,有两种情况
a、正方形的某个顶点在圆内
b、圆的上下左右点或圆心即(x,y+r)(x,y-r)(x-r,y)(x+r,y)(x,y)五个点的任意点在正方形内 (注意一定要判断圆心,有可能正方形的四个顶点都在圆上,此时也有面积交)
(2)正方形与圆有接触在一个点,有两种情况
a、正方形的某个顶点在圆上
b、圆的上下左右点即(x,y+r)(x,y-r)(x-r,y)(x+r,y)四个点的任意一个点在正方形上
(3)如果不是以上两种情况,则为相离

参考代码:

#include<bits/stdc++.h>
using namespace std;
int x,y,r,tx,ty,s;
int dotInCircle(int a,int b){
	 if((x-a)*(x-a)+(y-b)*(y-b)<r*r) return 1;
	 else if ((x-a)*(x-a)+(y-b)*(y-b)==r*r) return 2;
	 else return 0;
}
int dotInSquare(int a,int b){
	 if(a>tx&&a<tx+s&&b>ty&&b<ty+s) return 1;
	 else if(a==tx&&b>=ty&&b<=ty+s
	 ||a==tx+s&&b>=ty&&b<=ty+s
	 ||a>=tx&&a<=tx+s&&b==ty
	 ||a>=tx&&a<=tx+s&&b==ty+s) return 2;
	 else return 0;
}
bool overlap(){
 return dotInCircle(tx,ty)==1
 ||dotInCircle(tx+s,ty)==1
 ||dotInCircle(tx,ty+s)==1
 ||dotInCircle(tx+s,ty+s)==1
 ||dotInSquare(x,y)==1
 ||dotInSquare(x+r,y)==1
 ||dotInSquare(x-r,y)==1
 ||dotInSquare(x,y+r)==1
 ||dotInSquare(x,y-r)==1;
}
bool touch(){
 return dotInCircle(tx,ty)==2
 ||dotInCircle(tx+s,ty)==2
 ||dotInCircle(tx,ty+s)==2
 ||dotInCircle(tx+s,ty+s)==2
 ||dotInSquare(x+r,y)==2
 ||dotInSquare(x-r,y)==2
 ||dotInSquare(x,y+r)==2
 ||dotInSquare(x,y-r)==2;
}
int main(){
 cin>>x>>y>>r;
 cin>>tx>>ty>>s;
 if(overlap()) puts("2");
 else if(touch()) puts("1");
 else puts("0");
 return 0;
}

K World Cup Fever

添加链接描述

思路

最短路问题
首先预处理出 team1 的任意两个队员是否相距为 1(相距为 1 的条件为 team1 或 team2 中
除该两个队员之外的任意一个队员均不在该两个队员形成的线段上),如果相距为 1 将他们
的的距离设置为 1,否则将他们的距离设置为无穷大然后采用 Floyd 求出 1 到 n 的最短路径即
为答案

参考代码:

#include<bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
int n;
struct node{
 int x,y;
}team1[15],team2[15];
int dis[15][15];
bool between(node a,node b,node c){
 if(c.x>=min(a.x,b.x)&&c.x<=max(a.x,b.x)
 &&c.y>=min(a.y,b.y)&&c.y<=max(a.y,b.y)
 &&(c.y-a.y)*(b.x-a.x)==(b.y-a.y)*(c.x-a.x))
 return true;
 return false;
}
bool check(int a,int b){
	 for(int i=1;i<=n;i++)
		 if(a!=i&&b!=i&&between(team1[a],team1[b],team1[i])) return false;
     for(int i=1;i<=n;i++)
 if(between(team1[a],team1[b],team2[i])) return false;
	 return true;
}
int main(){
 cin>>n;
 for(int i=1;i<=n;i++)cin>>team1[i].x>>team1[i].y;
	 for(int i=1;i<=n;i++)cin>>team2[i].x>>team2[i].y;
	 for(int i=1;i<=n;i++){
		 for(int j=1;j<=n;j++){
			 if(i==j) dis[i][j]=0;
			 else if(check(i,j)) dis[i][j]=1;
			 else dis[i][j]=INF;
			 }
	 }

 for(int k=1;k<=n;k++){
	 for(int i=1;i<=n;i++){
		 for(int j=1;j<=n;j++){
			 dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
		 }
	 }
 }
 if(dis[1][n]==INF) puts("-1");
	 else cout<<dis[1][n]<<endl;
 return 0;
}

L Alex is Right

添加链接描述

思路

思路见代码

参考代码:

#include <math.h>
#include <stdio.h>
#define EPS 1e-6
#define RADIUS 6371
#define PI 3.14159265358979
typedef struct Vec {
 double x, y, z;
} Vec;
double min(double a, double b) {
 return a < b ? a : b;
}
Vec newVec(double x, double y, double z) {
 Vec v;
 v.x = x;
 v.y = y;
 v.z = z;
 return v;
}
Vec vecAdd(Vec a, Vec b) {
 return newVec(a.x + b.x, a.y + b.y, a.z + b.z);
}
Vec vecSub(Vec a, Vec b) {
 return newVec(a.x - b.x, a.y - b.y, a.z - b.z);
}
double vecDot(Vec a, Vec b) {
 return a.x * b.x + a.y * b.y + a.z * b.z;
}
double vecMag2(Vec v) {
 return vecDot(v, v);
}
double vecMag(Vec v) {
 return sqrt(vecMag2(v));
}
Vec vecScale(Vec v, double s) {
 return newVec(v.x * s, v.y * s, v.z * s);
}
Vec vecScaleTo(Vec v, double s) {
 return vecScale(v, s / vecMag(v));
}

Vec vecNormalize(Vec v) {
 return vecScaleTo(v, 1);
}
Vec vecCross(Vec a, Vec b) {
 return newVec(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x *
b.y - a.y * b.x);
}
// Given a plane defined by a, b, and c, returns the projection of ponto the plane.
Vec vecProj(Vec a, Vec b, Vec c, Vec p) {
	 Vec ab = vecSub(b, a);
	 Vec ac = vecSub(c, a);
	 Vec norm = vecNormalize(vecCross(ab, ac));
	 return vecSub(p, vecScale(norm, vecDot(vecSub(p, a), norm)));
}
int sig(double x) {
 if (fabs(x) < EPS)
 return 0;
 return x < 0 ? -1 : 1;
}

// Given the latitude and longitude (in degrees), returns the 3dpoint
// on the sphere of radius 6371km centered around the origin.
Vec getPointOnEarth(double lat, double lon) {
 lat = lat * PI / 180;
 lon = lon * PI / 180;
 double x = cos(lat) * cos(lon);
 double y = cos(lat) * sin(lon);
 double z = sin(lat);
 return vecScale(newVec(x, y, z), RADIUS);
}

int main(void) {
 int n;
 // Read in number of trips.
 scanf("%d", &n);

 // Get the points for the northPole and the origin.
 Vec northPole = getPointOnEarth(90, 0);
 Vec origin = newVec(0, 0, 0);
 for (int tripI = 0; tripI < n; tripI++) {
 	double lat0, lon0, lat1, lon1;
	 scanf("%lf", &lat0);
	 scanf("%lf", &lon0);
	 scanf("%lf", &lat1);
	 scanf("%lf", &lon1);
 int onEquator = fabs(lat0) < 1e-9 && fabs(lat1) < 1e-9;

 // Get the points of the two cities.
 Vec p0 = getPointOnEarth(lat0, lon0);
 Vec p1 = getPointOnEarth(lat1, lon1);
 // Calculate the initial minimum distance.
 double minDist = min(vecMag(vecSub(p0, northPole)),
	vecMag(vecSub(p1, northPole)));

 // Get a vector perpendicular to the plane defined by theorigin and the two cities.
     Vec norm = vecCross(p0, p1);
 // Project the north pole on to the plane defined by theorigin and the two cities.
     Vec proj = vecProj(origin, p0, p1, northPole);

 // Get the sign of the cross product (on the plane) from theprojected north pole to both cities.
 int sig0 = sig(vecDot(vecCross(proj, p0), norm));
 int sig1 = sig(vecDot(vecCross(proj, p1), norm));
 // If the projected point is between the smallest arc formedby the two, Alex is right.
 if (!onEquator && sig0 == -1 && sig1 == 1) {
 double originalMinDist = minDist;
 // Get the true minimum distance. 
     minDist = vecMag(vecSub(northPole, vecScaleTo(proj,RADIUS)));
 printf("Alex\n");
 } 
     else {
	 printf("Timothy\n");
 }
 // Print out the minimum distance.
	 printf("%.6f\n\n", minDist);
	 }
 return 0;
}

觉得还行 的可以三连支持一波!(hhhhh…)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值