UCF Local Programming Contest 2017(2020-04-06)
原题地址:https://www.jisuanke.com/contest/7195?view=challenges
A. Electric Bill
题意:分级收费,用电1000以下一档,以上一档,问应支付多少钱
AC代码:
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int main(){
int a,b,n,temp;
cin>>a>>b;
cin>>n;
for(int i=0;i<n;i++){
cin>>temp;
int ans=0;
if(temp>1000){
ans=1000*a+(temp-1000)*b;
}else{
ans=temp*a;
}
cout<<temp<<" "<<ans<<endl;
}
return 0;
}
B. Simplified Keyboard
题意:给定一个字母表,再给定两个字符串,问两字符串的类型。
1:长度相同,字母也相同
2:长度相同,字母不完全相同,但不同的字母是相邻的
3:不属于1和2的
思路:先预先处理字母表的相邻关系,在按个遍历。
用map<char,string> 键为字母,值为相邻字母;
AC代码:
#include<bits/stdc++.h>
#include<iostream>
#include<vector>
#include<queue>
#include<string>
#include<list>
#include<set>
#include<map>
#include<stack>
# define PI 3.14159265358979323846
using namespace std;
typedef long long ll;
const int maxn = 1010;
ll node[maxn];
char flag[3][10]={"abcdefghi","jklmnopqr","stuvwxyz0"};
map<char,string> mp;
int main()
{
for(int i=0;i<3;i++)
{
for(int j=0;j<9;j++)
{
if(j+1<9&&flag[i][j+1]>='a'&&flag[i][j+1]<='z') mp[flag[i][j]]+=flag[i][j+1];//you
if(i+1<3&&flag[i+1][j]>='a'&&flag[i+1][j]<='z') mp[flag[i][j]]+=flag[i+1][j];//xia
if(i-1>=0&&flag[i-1][j]>='a'&&flag[i-1][j]<='z') mp[flag[i][j]]+=flag[i-1][j];//shang
if(j-1>=0&&flag[i][j-1]>='a'&&flag[i][j-1]<='z') mp[flag[i][j]]+=flag[i][j-1];//zuo
if(i-1>=0&&j+1<9&&flag[i-1][j+1]>='a'&&flag[i-1][j+1]<='z') mp[flag[i][j]]+=flag[i-1][j+1];//you shang
if(i+1<3&&j+1<9&&flag[i+1][j+1]>='a'&&flag[i+1][j+1]<='z') mp[flag[i][j]]+=flag[i+1][j+1];// you xia
if(i-1>=0&&j-1>=0&&flag[i-1][j-1]>='a'&&flag[i-1][j-1]<='z') mp[flag[i][j]]+=flag[i-1][j-1];//zuo shang
if(i+1<3&&j-1>=0&&flag[i+1][j-1]>='a'&&flag[i+1][j-1]<='z') mp[flag[i][j]]+=flag[i+1][j-1];//zuo xia
}
}
int n;
cin>>n;
while(n--)
{
string s1,s2;
cin>>s1>>s2;
if(s1==s2)cout<<1<<endl;
else if(s1.length()==s2.length())
{
int f = 1;
for(int i=0;i<s1.length();i++)
{
char t1 = s1[i];
char t2 = s2[i];
if(t1==t2) continue;
if(mp[t1].find(t2)==string::npos)
{
f = 0;
break;
}
}
if(f) cout<<2<<endl;
else cout<<3<<endl;
}
else cout<<3<<endl;
}
return 0;
}
C. Singin' in the Rain
题意:给出一个歌单顺序,每次听完上一首歌后需要通过按上一曲或下一曲直至达到下一首要听的歌,问要听完整个给出的歌单顺序,需要按多少次按钮
思路:每两个之间分别计算,向前一首需要按的次数,和向后一首需要按的次数,取较小值即可,注意的是听完歌曲n后会自动调到n+1,如果听完后按下一首,此时应该是第n+2首
AC代码:
#include<bits/stdc++.h>
#include<iostream>
#include<vector>
#include<queue>
#include<string>
#include<list>
#include<set>
#include<map>
#include<stack>
using namespace std;
typedef long long ll;
const int maxn = 1e3+10;
ll node[maxn];
int main()
{
int N;
cin>>N;
while(N--)
{
ll t,s;
cin>>t>>s;
for(int i=0;i<s;i++)
{
cin>>node[i];
}
ll sum = 0;
for(int i=1;i<s;i++)
{
ll a = (node[i-1]+1)%t;
ll b = node[i];
if(a<b)
{
ll ans1 = b-a;
ll ans2 = a+(t-b);
sum+=min(ans1,ans2);
// cout<<"1:"<<min(ans1,ans2)<<endl;
}
else if(a>b)
{
ll ans1 = (t-a)+b;
ll ans2 = a-b;
sum+=min(ans1,ans2);
// cout<<"2:"<<min(ans1,ans2)<<endl;
}
}
cout<<sum<<endl;
}
return 0;
}
D. Editor Navigation
题意:word 里边有几行字母,给定初始位置和目标位置,问光标最少移动几次
思路:BFS但要注意 光标在首尾和上下移动时字母长度不同的情况
AC代码:
#include<bits/stdc++.h>
#include<iostream>
#include<vector>
#include<queue>
#include<string>
#include<list>
#include<set>
#include<map>
#include<stack>
# define PI 3.14159265358979323846
using namespace std;
typedef long long ll;
const int maxn = 1010;
const int N = 125,M = 85;
int T,n,bx,by,ex,ey,num[N];
bool vis[N][M];
int dit[4][2] = {-1,0,1,0,0,-1,0,1};
struct node
{
int x,y,cnt;//cnt 表示移动次数
};
void BFS()
{
queue<node>q;
q.push({bx,by,0});
memset(vis,0,sizeof(vis));
vis[bx][by] = 1;
while(!q.empty())
{
node tmp = q.front();
q.pop();
int x = tmp.x;
int y = tmp.y;
int cnt = tmp.cnt;
if(x==ex&&y==ey)
{
cout<<cnt<<endl;
return ;
}
for(int i=0;i<4;i++)
{
int nx = x+dit[i][0];
int ny = y+dit[i][1];
if(nx>=1&&nx<=n)
{
if(i==0||i==1)//上下移动时
{
if(ny<=num[nx]&&!vis[nx][ny])//没有超出范围
{
vis[nx][ny]=1;
q.push({nx,ny,cnt+1});
}
if(ny>num[nx]&&!vis[nx][ny])//超出范围
{
vis[nx][num[nx]]=1;
q.push({nx,num[nx],cnt+1});
}
}
else//左右
{
if(ny==-1&&i==2&&x-1>=1)//在开头,左移则移动到上层末尾
{
int tx = x-1;
int ty = num[tx];
if(!vis[tx][ty])
{
vis[tx][ty]=1;
q.push({tx,ty,cnt+1});
}
}
if(ny==num[x]+1&&i==3&&x+1<=n)
{
int tx = x+1;
int ty = 0;
if(!vis[tx][ty])
{
vis[tx][ty]=1;
q.push({tx,ty,cnt+1});
}
}
if(ny>=0&&ny<=num[x]&&!vis[nx][ny])
{
vis[x][ny]=1;
q.push({x,ny,cnt+1});
}
}
}
}
}
}
int main()
{
int T;
cin>>T;
while(T--)
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>num[i];
}
cin>>bx>>by>>ex>>ey;
BFS();
}
return 0;
}
E. Simple Darts
题意:给定一个圆形靶,分成w份扇形,每个扇形又分成三部分,分别给出b,d,s,分别为靶心,双倍区,单倍区。给定落点问最终得分。
思路:求出得分需要知道在几倍区和所在区的序号
通过求距离可知在几倍区
atan2函数可以算出与x轴正方向的夹角
AC代码:
#include<bits/stdc++.h>
#include<iostream>
#include<vector>
#include<queue>
#include<string>
#include<list>
#include<set>
#include<map>
#include<stack>
# define PI 3.14159265358979323846
using namespace std;
typedef long long ll;
const int maxn = 1e5+10;
double node[maxn];
int w,b,d,s;
double flen(double x,double y) //计算点到原点的距离
{
double a = x*x;
double b = y*y;
return sqrt(a+b);
}
double fans(double x,double y)//计算 点与原点组成直线与x正方向的角度
{
return atan2(y,x)*180/PI;//范围是-180到180;
}
int main()
{
ll N;
cin>>N;
while(N--)
{
cin>>w>>b>>d>>s;
double tt = 360*1.0/w; //将圆分成w份
node[1] = tt;//node记录每份的角度边界
for(ll i=2;i<=w;i++)
{
node[i] = node[i-1]+tt;
}
// d=b+d;
// s=d+s;
ll t;
cin>>t;
ll sum = 0;
while(t--)
{
ll flag=0;
double x,y;
cin>>x>>y;
double len = flen(x,y);
// cout<<len<<" ";
//通过距离算出 是单环还是双环还是圆心
if(len<b) flag=1;
else if(len<d) flag=2;
else if(len<s) flag=3;
if(flag==1)
{
sum+=50;
// cout<<"!1:50"<<endl;
}
if(flag==2)
{
double tans = fans(x,y);//角度
if(tans<0) tans = 360+tans;// 负数角度变成正数
ll f = 1;
//循环 找到 所处哪个 楔形块
for(f;f<=w;f++)
{
if(node[f]>tans) break;
}
sum+=2*f;
// cout<<"!2:"<<f<<endl;
}
if(flag==3)
{
double tans = fans(x,y);
if(tans<0) tans = 360+tans;
ll f = 1;
for(f;f<=w;f++)
{
if(node[f]>tans) break;
}
sum+=f;
// cout<<"!3:"<<f<<endl;
}
}
cout<<sum<<endl;
}
return 0;
}