目录
A - Four Points
签到,给出和xy轴平行的矩形的三个点,求第四个点
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#include<set>
#include<vector>
#include<cstring>
#include<string>
using namespace std;
int main()
{
int x1,x2,x3,y1,y2,y3;
cin>>x1>>y1>>x2>>y2>>x3>>y3;
if(x1==x2)
cout<<x3<<" ";
else if(x3==x2)
cout<<x1<<" ";
else if(x1==x3)
cout<<x2<<" ";
if(y1==y2)
cout<<y3<<" ";
else if(y3==y2)
cout<<y1<<" ";
else if(y1==y3)
cout<<y2<<" ";
return 0;
}
B - Get Closer
签到,给出一个点,以这个点为方向,求从(0,0)前进1个单位长度后的位置坐标
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#include<set>
#include<vector>
#include<cstring>
#include<string>
using namespace std;
int main()
{
double a,b,c=1;
cin>>a>>b;
if(a==0)
printf("0 1");
else if(b==0)
printf("1 0");
else
{
double x,y,ans;
ans=sqrt((a*a)+(b*b));
x=a/ans;
y=b/ans;
printf("%.8lf %.8lf",x,y);
}
return 0;
}
C - Coupon
有n个商品,你有k张打折券,每张券可以减免x元,当商品减免x元后为负数时直接为0元.
模拟,首先遍历商品数组,在不把商品减免为0的情况下尽量进行减免.然后再把剩下的商品从大到小排序,再从头开始遍历,将前面的商品化为免费,知道券用完即可.
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#include<set>
#include<vector>
#include<cstring>
#include<string>
#define int long long
using namespace std;
int arr[200005];
bool cmp(int a,int b)
{
return a>b;
}
signed main()
{
int n,k,x;
scanf("%lld%lld%lld",&n,&k,&x);
for(int i=0;i<n;i++)
scanf("%lld",&arr[i]);
for(int i=0;i<n;i++)
{
if(k==0)
break;
if(k>arr[i]/x)
{
k-=(arr[i]/x);
arr[i]-=(arr[i]/x)*x;
}
else
{
arr[i]-=k*x;
k=0;
continue;
}
}
sort(arr,arr+n,cmp);
int ans=0;
for(int i=0;i<n;i++)
{
if(arr[i]==0)
break;
if(k!=0)
{
k--;
continue;
}
ans+=arr[i];
}
printf("%lld",ans);
return 0;
}
D - 2-variable Function
给你一个数字n,求一个大于它且满足f(a,b)=a^3+a^2b+ab^2+b^3(a,b为非负数)的数的最小值.
双指针做法,分别从1和1e6两个指针进行操作,当两者进行f(l,r)运算时,大于n时就让右端点向左移动,小于n则左端点向右移动,这样可以筛去很多不合要求的情况.在剩余情况中取最小值即可.
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#include<set>
#include<vector>
#include<cstring>
#include<string>
#define int long long
using namespace std;
int n;
signed main()
{
int ans=1e18+1;
scanf("%lld",&n);
int r=1000000;
for(int l=0;l<=1000000;l++)
{
int temp=l*l*l+r*r*r+r*r*l+l*l*r;
while(temp>=n&&r>=0)
{
ans=min(ans,temp);
r--;
temp=l*l*l+r*r*r+r*r*l+l*l*r;
}
}
printf("%lld",ans);
return 0;
}
E - Bishop 2
搜索+剪枝
有一个棋盘,'.'可以走,'#'不可以走也不可以越过,棋子只能向左上左下右上右下四个方向移动(不论移动多长都算一步),问最少步数.
该题在基础的bfs基础上多加一个标记,vis[x][y][to],to是四个方向的状态,我们只需要标记每个点从四个方向的状态即可.要注意的是剪枝时,当一个点不能往前走或者已经从这个点的方向走过了,需要直接break.
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#include<set>
#include<vector>
#include<cstring>
#include<string>
using namespace std;
int n,sx,sy,ex,ey;
int dx[4]={1,1,-1,-1};
int dy[4]={1,-1,1,-1};
int vis[1505][1505][4];
char ma[1505][1505];
struct node
{
int x,y,step;
};
void bfs()
{
queue<node>qu;
node bef;
bef={sx,sy,0};
qu.push(bef);
while(qu.size())
{
bef=qu.front();
qu.pop();
if(bef.x==ex&&bef.y==ey)
{
printf("%d\n",bef.step);
return;
}
for(int i=0;i<4;i++)
{
for(int j=1;;j++)
{
int xx=bef.x+j*dx[i],yy=bef.y+j*dy[i];
if(xx<1||xx>n||yy<1||yy>n)
break;
if(ma[xx][yy]=='#')
break;
if(vis[xx][yy][i]==1)
break;
vis[xx][yy][i]=1;
qu.push({xx,yy,bef.step+1});
}
for(int j=1;;j++)
{
int xx=bef.x+j*dx[i],yy=bef.y+j*dy[i];
if(xx<1||xx>n||yy<1||yy>n)
break;
if(ma[xx][yy]=='#')
break;
if(vis[xx][yy][i]==1)
break;
vis[xx][yy][i]=1;
qu.push({xx,yy,bef.step+1});
}
for(int j=1;;j++)
{
int xx=bef.x+j*dx[i],yy=bef.y+j*dy[i];
if(xx<1||xx>n||yy<1||yy>n)
break;
if(ma[xx][yy]=='#')
break;
if(vis[xx][yy][i]==1)
break;
vis[xx][yy][i]=1;
qu.push({xx,yy,bef.step+1});
}
for(int j=1;;j++)
{
int xx=bef.x+j*dx[i],yy=bef.y+j*dy[i];
if(xx<1||xx>n||yy<1||yy>n)
break;
if(ma[xx][yy]=='#')
break;
if(vis[xx][yy][i]==1)
break;
vis[xx][yy][i]=1;
qu.push({xx,yy,bef.step+1});
}
}
}
printf("-1");
}
int main()
{
scanf("%d",&n);
scanf("%d%d%d%d",&sx,&sy,&ex,&ey);
for(int i=1;i<=n;i++)
scanf("%s",ma[i]+1);
bfs();
return 0;
}