A - JiaoZhu的粉丝
#include<iostream>
#include<cstdio>
using namespace std;
int main()
{
int n;
cin>>n;
cout<<"UserName-------GY"<<endl;
for(int i=1;i<=n;i++)
cout<<" JiaoZhuV5"<<endl;
cout<<"-----2021/10/24----";
return 0;
}
B - Vvvvvegetable(by gy)
- 可以用一个 12x3 大小的桶(实际用时要稍微开大一点避免越界)来维护相应进度的玩家数量,然后查找排名第 n/2 的玩家进度,对于比该进度低的询问输出“They are very Vvvvvegetable.”,否则输出相应玩家的个数。
#include <bits/stdc++.h>
using namespace std;
int tong[15][5];
int main()
{
int n,a,b,mid_a,mid_b;
cin>>n;
for(int i=1;i<=n;i++)
{
scanf("%d %d",&a,&b);
tong[a][b]++;
}
int sum=0;
for(int i=12;i>=1;i--)
for(int j=3;j>=1;j--)
{
if(sum<n/2)
{
mid_a=i;
mid_b=j;
}
sum+=tong[i][j];
}
int q;
cin>>q;
while(q--)
{
scanf("%d %d",&a,&b);
if(a>mid_a||(a==mid_a&&b>=mid_b))
printf("%d\n",tong[a][b]);
else
printf("They are very Vvvvvegetable.\n");
}
return 0;
}
C - LHL爬网线(by lhl)
D - 铺地毯
- 求的是给定位置最上面的地毯,将输入保存后倒着遍历即可。
#include<iostream>
using namespace std;
int main()
{
int n,x,y,xx,yy;
cin>>n;
int car[n+1][5];
for(int i=1;i<=n;i++)
for(int j=1;j<=4;j++)
cin>>car[i][j];
cin>>x>>y;
for(int i=n;i>=1;i--)
{
xx=car[i][1]+car[i][3];
yy=car[i][2]+car[i][4];
if(car[i][1]<=x&&car[i][2]<=y&&xx>=x&&yy>=y)
{
cout<<i;
return 0;
}
}
cout<<"-1";
return 0;
}
E - 马的遍历
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
int x,y,m,n,ans[405][405],xx[8]={-1,-1,1,1,2,2,-2,-2},yy[8]={2,-2,2,-2,1,-1,1,-1};
struct node{
int x,y,step;
};
int main()
{
cin>>n>>m>>x>>y;
memset(ans,-1,sizeof(ans));
queue<node>q;
q.push({x,y,0});
ans[x][y]=0;
while(!q.empty())
{
node nw=q.front();
q.pop();
for(int i=0;i<8;i++)
{
int nx=nw.x+xx[i],ny=nw.y+yy[i];
if(nx>0&&nx<=n&&ny>0&&ny<=m&&ans[nx][ny]==-1)
{
ans[nx][ny]=nw.step+1;
q.push({nx,ny,ans[nx][ny]});
}
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
printf("%-5d",ans[i][j]);
cout<<endl;
}
return 0;
}
F - 选数
- dfs,每次选到第k个数,如果当前和是素数,判断是否被标记过,未被标记答案加1。
- dfs与bfs算法
#include<iostream>
#include<cmath>
using namespace std;
int k,ans,n,y[5000005];
bool yy[5000005];
inline bool prime(int x)
{
for(register int i=2;i<=sqrt(x);i++)
if(x%i==0)
return false;
return true;
}
void dfs(int a,int tmp,int m)
{
if(a==k)
{
if(prime(tmp))
ans++;
return;
}
for(int i=m;i<=n;i++)
if(!yy[i])
{
yy[i]=1;
dfs(a+1,tmp+y[i],i+1);
yy[i]=0;
}
}
int main()
{
cin>>n>>k;
for(int i=1;i<=n;i++)
{
cin>>y[i];
}
dfs(0,0,1);
cout<<ans;
return 0;
}
G - 忧郁的蘑菇
- 不妨思考一下,在所有正方形中,面积相对较大的正方形存放难度肯定比面积较小的正方形高(大正方形能放的区域,小正方形一定可以,但是反之不行),所以可以按照面积从大到小的顺序存放正方形,又因为大区域刚好可以分割成 9 个小区域,我们可以利用深搜不断缩小区域面积,直到刚好等于当前需要的面积(请仔细思考为什么可以这么分割)。(如图把左边一个大区域分成 9 块,取出淡蓝色块再将其看做一个大区域…以此类推)
#include <bits/stdc++.h>
using namespace std;
const int maxn=5e4+5;
int cnt,n;
struct e
{
int val,id,ansx,ansy;
}air[maxn];
bool com(e a,e b)
{
return a.val>b.val;
}
bool com2(e a,e b)
{
return a.id<b.id;
}
void dfs(int l,int top,int r,int bottom)
{
if(cnt>n)
return ;
if(air[cnt].val==r-l+1)
{
air[cnt].ansx=r+l>>1;
air[cnt].ansy=top+bottom>>1;
cnt++;
return ;
}
else
{
int sonlen=(r-l+1)/3,ll=l,tt=top;
for(int i=1;i<=3;i++)
for(int j=1;j<=3;j++)
dfs(l+(i-1)*sonlen,tt+(j-1)*sonlen,ll+i*sonlen-1,tt+j*sonlen-1);
}
}
int main()
{
int r;
cin>>r>>n;
cnt=1;
for(int i=1;i<=n;i++)
{
air[i].id=i;
scanf("%d",&air[i].val);
}
sort(air+1,air+n+1,com);
dfs(1,1,r,r);
sort(air+1,air+n+1,com2);
for(int i=1;i<=n;i++)
printf("%d %d\n",air[i].ansx,air[i].ansy);
return 0;
}
H - 难题
- m=n,问题简化成了对单个数进行素数判断,判断n是不是素数只需要从2枚举到sqrt(n)看看有没有它的因子即可,主义,1不是素数。
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int main()
{
int n,m;
cin>>n>>m;
if(n==1)
{
cout<<0;
return 0;
}
m=sqrt(n);
for(int i=2;i<=m;i++)
{
if(!(n%i))
{
cout<<0;
return 0;
}
}
cout<<n;
return 0;
}
I - 营救
- 方法一:二分或倍增 + bfs,二分最大拥挤度,bfs判断当前拥挤度是否可行。
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
struct edge{
int v,w,next;
}e[1000005];
int n,m,s,fi[500005],gi[500005],wi[500005],cnt,front[20005],t,lefts,rights,mid;
long long d[10005],inf=2147483647;
inline void inserts(int u,int v,int w){
cnt++;
e[cnt].v=v;
e[cnt].w=w;
e[cnt].next=front[u];
front[u]=cnt;
}
int inq[100001];
void spfa(){
queue<int> q;
memset(inq,0,sizeof(inq));
for(int i=1;i<=n;i++)
d[i]=inf;
d[s]=0;
inq[s]=1;
q.push(s);
while(!q.empty()){
int u=q.front();q.pop();inq[u]=0;
for(int i=front[u];i>=0;i=e[i].next){
int v=e[i].v,w=e[i].w;
if(d[u]+w<d[v]&&w<=mid){
d[v]=d[u]+w;
if(!inq[v]){
inq[v]=1;
q.push(v);
}
}
}
}
}
int main()
{
memset(front,-1,sizeof(front));
cin>>n>>m>>s>>t;
for(int i=1;i<=m;i++)
{
cin>>fi[i]>>gi[i]>>wi[i];
inserts(fi[i],gi[i],wi[i]);
inserts(gi[i],fi[i],wi[i]);
rights=max(rights,wi[i]);
}
while(lefts<=rights)
{
mid=(lefts+rights)>>1;
spfa();
if(d[t]==inf)
lefts=mid+1;
else
rights=mid-1;
}
cout<<lefts;
return 0;
}
J - 旅行 Tour
- 双向TSP问题,通过DP解决。
- 一去一回看成两个单向的去,d(i,j)表示当前前面在i后面在j时所走的最短距离(一般可以认为的加一些限制来方便求解),具体做法详见紫书动态规划篇。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
const double maxn=0x3f3f3f3f;
int x[1005],y[1005],n;
double d[1005][1005];
double ojld(int a,int b,int c,int d)
{
return sqrt((double)((a-c)*(a-c)+(b-d)*(b-d)));
}
int main()
{
while(cin>>n&&n!=EOF)
{
for(int i=1;i<=n;i++)
scanf("%d%d",&x[i],&y[i]);
for(int i=0;i<=n;i++)
for(int j=0;j<=n;j++)
d[i][j]=maxn;
d[n][n]=0;d[n][n-1]=ojld(x[n-1],y[n-1],x[n],y[n]);
for(int i=n-1;i>=2;i--)
for(int j=i-1;j>=1;j--)
d[i][j]=min(d[i+1][i]+ojld(x[j],y[j],x[i+1],y[i+1]),d[i+1][j]+ojld(x[i],y[i],x[i+1],y[i+1]));
printf("%.2lf\n",d[2][1]+ojld(x[1],y[1],x[2],y[2]));
}
return 0;
}
K - 归程