【2023牛客寒假算法基础集训营1】小复盘
A World Final? World Cup! (I)
4种情况,想全就过。
A先踢 numa
A当前踢进的数量 numb
B当前踢进的数量
①A踢完/A必赢/B还能踢k
脚 numa>numb+k
②A踢完/B必赢/A还能踢k
脚 numb>numa+k
③B踢完/A必赢/B还能踢k
脚 numa>numb+k
④B踢完/B必赢/A还能踢k
脚 numb>numa+k
#include<bits/stdc++.h>
using namespace std;
int main(){
int t;
cin>>t;
while(t--){
string s;
cin>>s;
vector<int> a,b;
for(int i=0;i<10;i++){
if(i&1) b.push_back(s[i]-'0');
else a.push_back(s[i]-'0');
}
int numa=0,numb=0;
int f=0;
for(int i=0;i<5;i++){
if(a[i]==1) numa++;
if(numa>numb+(5-i)){
f=i*2+1;
break;
}
if(numb>numa+(4-i)){
f=i*2+1;
break;
}
if(b[i]==1) numb++;
if(numb>numa+(4-i)){
f=(i+1)*2;
break;
}
if(numa>numb+(4-i)){
f=(i+1)*2;
break;
}
}
if(!f){
cout<<-1<<endl;
}else{
cout<<f<<endl;
}
}
return 0;
}
C 现在是,学术时间 (I)
“该教授发表的所有论文中,有至少H篇论文的引用量大于等于H”这一命题成立的最大的H。
尽可能让所有教授的H指数之和最大
显然可以看出,每个教授分一篇得到的H指数最大。
因为分的人越少,有的论文就越多,对引用量的要求就越高,所以分担给每个教授最合理。
唯一注意,引用量为0的H指数为0,其余为1,累加计算即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
ll a[N];
int main(){
int t;
cin>>t;
while(t--){
int n;
cin>>n;
int num=0;
for(int i=1;i<=n;i++){
cin>>a[i];
if(a[i]==0) num++;
}
cout<<n-num<<endl;
}
return 0;
}
D 现在是,学术时间 (II)
三种情况,分别处理。
① p点横纵坐标均大于等于矩阵内任意一点坐标。
② p点横纵坐标均小于等于矩阵内任意一点坐标。
③ 除上以外。
在第三种情况中,需要对并集面积做加法,分两种情况讨论。
一个是在矩阵上方,一个是在矩阵右方。
分别计算即可得到答案。
#include<bits/stdc++.h>
using namespace std;
double iou(int x,int y,int px,int py,int tx,int ty){
double res=0;
if(tx==0&&ty==0) return 0;
double jiao=(double)(abs(px-x))*(double)(abs(py-y));
double bing=(double)(tx*ty);
res=jiao/bing;
return res;
}
double iou2(int s,int ss){
double res=0;
if(s==0) return 0;
double jiao=(double)ss;
double bing=(double)s;
res=jiao/bing;
//cout<<jiao<<" "<<bing<<endl;
return res;
}
int main(){
int t;
cin>>t;
while(t--){
int x,y,px,py;
cin>>x>>y>>px>>py;
double ans=0;
if(x>=px&&y>=py){
ans=max(ans,iou(0,0,px,py,x,y));
ans=max(ans,iou(0,y,px,py,x,y));
ans=max(ans,iou(x,0,px,py,x,y));
ans=max(ans,iou(x,y,px,py,x,y));
//cout<<1<<endl;
}else if(x<=px&&y<=py){
ans=iou(0,0,x,y,px,py);
//cout<<2<<endl;
}else if(x<=px&&y>=py){
ans=max(ans,iou2(px*py+(y-py)*x,x*py));
ans=max(ans,iou2((y-py)*px+py*x,x*(y-py)));
//cout<<3<<endl;
}else{
ans=max(ans,iou2((x-px)*py+px*y,(x-px)*y));
ans=max(ans,iou2(px*py+(x-px)*y,px*y));
//cout<<4<<endl;
}
cout<<ans<<endl;
}
return 0;
}
H 本题主要考察了DFS
做复杂了,想太多。
因为拼图是一定能拼好的,所以不需要考虑太多,直接计数缺的和补的个数,差值一定就是最后隐藏的这块拼图来补。
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
int vis[440*4];
int x,y;
int len;
vector<pii> ve;
vector<int> vp;
void dfs(int id){
if(vis[id]) return ;
vis[id]=1;
int f=0;
for(int i=0;i<len;i++){
if(!vis[i]&&ve[id].second!=ve[i].second&&ve[id].first!=ve[i].first){
vis[i]=1;
f=1;
break;
}
}
if(!f){
vis[id]=1;
vp.push_back(id);
}
for(int i=0;i<len;i++){
if(!vis[i]){
dfs(i);
}
}
}
int main(){
int t;
cin>>t;
while(t--){
int n;
x=0;y=0;
string s;
cin>>n;
for(int i=1;i<=n*n-1;i++){
cin>>s;
for(int j=0;j<4;j++){
if(s[j]=='0') continue;
ve.push_back(make_pair(s[j]-'0',i));
}
}
//sort(ve.begin(),ve.end());
len=(int)ve.size();
if(len){
dfs(0);
for(int i=0;i<vp.size();i++){
int id=vp[i];
if(ve[id].first==1) y++;
if(ve[id].first==2) x++;
}
cout<<10-x+y<<endl;
}
else{
cout<<10<<endl;
}
memset(vis,0,sizeof(vis));
ve.clear();
vp.clear();
}
return 0;
}
K 本题主要考察了dp
根据给定n和m直接构造出对应的01序列。
构造方法就是能是好序列就是好序列,剩下的没办法,就让它成坏序列。
这种构造方法构造出来的序列,一定是坏序列最少的。
然后维护一个长度为3的区间段来扫描一遍序列,记录有多少个坏序列即可。
#include<bits/stdc++.h>
using namespace std;
int a[1010];
int main(){
int n,m;
cin>>n>>m;
int num1=m,num0=n-m;
int idx=1;
while(idx<=n){
if(num1){
a[idx++]=1;
num1--;
}
if(num0){
a[idx++]=0;
num0--;
}
if(num0){
a[idx++]=0;
num0--;
}
}
int ans=0;
int l=1,r=3;
while(r<=n){
int cnt=0;
for(int i=l;i<=r;i++){
if(a[i]==1) cnt++;
}
if(cnt>=2) ans++;
l++;r++;
}
cout<<ans<<endl;
return 0;
}
L 本题主要考察了运气
我蒙的,试了38次。
#include<bits/stdc++.h>
using namespace std;
int main(){
cout<<32<<endl;
return 0;
}
M 本题主要考察了找规律
非常好想的三维dp,比赛的时候以为会超时,没写,结果给了2s。
算空间,开二维。
想i
和j
以及dp[i][j]
分别代表什么含义即可。
i
表示第i个人
j
表示还剩j个仙贝
dp[i][j]
表示在...的情况下,所能获得好感度的最大值。
状态转移方程为dp[i][j]=max{dp[i-1][j-x]+x/j}
#include<bits/stdc++.h>
using namespace std;
double dp[510][510];
int main(){
cout<<setiosflags(ios::fixed)<<setprecision(8);
int n,m;
cin>>n>>m;
for(int i=1;i<=m;i++){
dp[1][i]=1;
}
for(int i=2;i<=n;i++){
for(int j=1;j<=m;j++){
for(int x=0;x<=j;x++){
dp[i][j]=max(dp[i][j],dp[i-1][j-x]+(double)x/(double)j);
}
}
}
cout<<dp[n][m]<<endl;
return 0;
}
E 鸡算几何
中档题
F 鸡玩炸蛋人
中档题
G 鸡格线
中档题