| 题目 | 难度 | 知识点 |
|---|---|---|
| A 三角形 | ★★ | 贪心,指针 |
| B 博弈论 | ★★ | 抽屉原理,字符串 |
| C 病菌感染 | ★ | 模拟 |
| D 郊区春游 | ★★ | floyd,状压DP,TSP |
| E 浮点数输出 | ★ | 签到 |
| F 等价串 | ★★ | 构造 |
| G 黑白棋 | ★★ | 模拟 |
| H 相邻的糖果 | ★★ | 贪心 |
| I 合唱队形 | ★★ | 二分 |
| J 强迫症 | ★ | 构造,贪心 |
三角形
将其从小到大排,最大的一定是三个连续的,三个指针模拟移动即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long int LL;
typedef pair<LL,LL> PII;
LL n,m;
vector<PII>ve;
int main(void)
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
int x; cin>>x;
ve.push_back({x,i});
}
sort(ve.begin(),ve.end());
while(m--)
{
int op; cin>>op;
LL a=-1,b=-1,c=-1,flag=0;
for(int i=ve.size()-1;i>=0;i--)
{
if(ve[i].second==op) {
continue;
}
if(a==-1) a=ve[i].first;
else if(b==-1) b=ve[i].first;
else if(c==-1) c=ve[i].first;
if( c!=-1 && a<b+c )
{
flag=1;
cout<<a+b+c<<endl;
break;
}
if(c!=-1) a=b,b=c,c=-1;
}
if(!flag) cout<<-1<<endl;
}
return 0;
}
博弈论
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int a[N],n,st[N];
int main(void)
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int k=1;k<=5;k++)
{
for(int i=1;i<=n;i++)
{
int l=i,r=i+k-1;
int sum=0;
for(int j=l;j<=r;j++) sum=sum*10+a[j];
if(sum>1e5) continue;
st[sum]++;
}
}
for(int i=0;i<=1e5;i++)
if(!st[i])
{
cout<<i;
return 0;
}
return 0;
}
#include<bits/stdc++.h>
using namespace std;
int main(void)
{
int n,x;
string a;
cin>>n;
for(int i=0;i<n;i++) cin>>x,a+=to_string(x);
for(int i=0;i<=1e4+10;i++)
{
if(a.find(to_string(i))==-1)
{
cout<<i;
return 0;
}
}
return 0;
}
病菌感染
#include<bits/stdc++.h>
using namespace std;
const int N=1010;
int a[N][N],n,m,x,y;
int dx[4]={-1,0,0,1};
int dy[4]={0,-1,1,0};
void solve(int x,int y)
{
int cnt=0;
for(int i=0;i<4;i++)
{
int tempx=x+dx[i],tempy=dy[i];
if(tempx<1||tempx>n||tempy<1||tempy>n) continue;
if(a[tempx][tempy]) cnt++;
}
if(cnt>=2) a[x][y]++;
}
int main(void)
{
cin>>n>>m;
while(m--) cin>>x>>y,a[x][y]++;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++) solve(i,j);
int cnt=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(a[i][j]) cnt++;
if(cnt==n*n) puts("YES");
else puts("NO");
return 0;
}
郊区春游
先floyd再状压DP,f[i][j],是i状态且最后的落脚点是j的最小花费。
#include<bits/stdc++.h>
using namespace std;
const int N=220;
int g[N][N],n,m,r;
int f[1<<15][20],a[20];
int main(void)
{
cin>>n>>m>>r;
for(int i=0;i<r;i++) cin>>a[i];
memset(g,0x3f,sizeof g);
for(int i=1;i<=n;i++) g[i][i]=0;
while(m--)
{
int a,b,c; cin>>a>>b>>c;
g[a][b]=g[b][a]=min(g[a][b],c);
}
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
memset(f,0x3f,sizeof f);
for(int i=0;i<r;i++) f[1<<i][i]=0;
for(int i=0;i<(1<<r);i++)
{
for(int j=0;j<r;j++)
{
if(i>>j&1)
{
for(int k=0;k<r;k++)
{
if(i>>k&1)
{
f[i][j]=min(f[i][j],f[i-(1<<j)][k]+g[a[k]][a[j]]);
}
}
}
}
}
int ans=1e9;
for(int i=0;i<r;i++) ans=min(ans,f[(1<<r)-1][i]);
cout<<ans;
return 0;
}
浮点数输出
#include<bits/stdc++.h>
using namespace std;
int main(void)
{
string s; cin>>s;
cout<<s;
return 0;
}
等价串
A->B,反过来B->A,故取一个中间状态都弄成"0"串。
#include<bits/stdc++.h>
using namespace std;
int main(void)
{
int t; cin>>t;
while(t--)
{
int n,m; cin>>n>>m;
string a,b; cin>>a>>b;
string temp1,temp2;
for(int i=0;i<a.size();i++)
if(a[i]=='1') temp1+="00";
else temp1+=a[i];
for(int i=0;i<b.size();i++)
if(b[i]=='1') temp2+="00";
else temp2+=b[i];
if( (temp1.size()%3) == (temp2.size()%3) ) puts("YES");
else puts("NO");
}
return 0;
}
黑白棋
#include<bits/stdc++.h>
using namespace std;
int a[15][15];
int dx[8]={-1,-1,-1,0,0,1,1,1};
int dy[8]={-1,0,1,-1,1,-1,0,1};
int o;
int solve(int x,int y,int o)
{
int cnt=0;
for(int d=0;d<8;d++)
{
int tempx=x+dx[d],tempy=y+dy[d];
if(a[tempx][tempy]==-1) continue;
if(a[tempx][tempy]!=1-o) continue;
for(int stx=tempx,sty=tempy;;stx+=dx[d],sty+=dy[d])
{
if(a[stx][sty]==-1) break;
if(a[stx][sty]==o)
{
for(; (tempx!=stx) || (tempy!=sty) ;tempx+=dx[d],tempy+=dy[d])
{
a[tempx][tempy]=o;
cnt++;
}
break;
}
}
}
return cnt;
}
int main(void)
{
int x,y;
memset(a,-1,sizeof a);
a[4][5]=a[5][4]=0;
a[4][4]=a[5][5]=1;
while(cin>>x>>y)
{
if(solve(x,y,o)) a[x][y]=o,o=o^1;
else solve(x,y,o^1),a[x][y]=o^1;
}
int cnt0=0,cnt1=0;
for(int i=1;i<=8;i++)
for(int j=1;j<=8;j++)
if(a[i][j]==0) cnt0++;
else if(a[i][j]==1) cnt1++;
printf("%d:%d",cnt0,cnt1);
return 0;
}
相邻的糖果
显然一个区间大于x,一定优先从后往前吃多余的糖果。
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
typedef long long int LL;
LL a[N],n,m,x,ans;
int main(void)
{
cin>>n>>m>>x;
for(int i=1;i<=n;i++) cin>>a[i];
LL ans=0,sum=0;
for(int i=1;i<=n;i++)
{
if(i>m) sum-=a[i-m];
sum+=a[i];
if(sum>x)
{
ans+=(sum-x);
a[i]=a[i]-(sum-x);
sum=x;
}
}
cout<<ans;
return 0;
}
合唱队形
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
string a;
int s[N],n;
bool check(int x)
{
for(int i=1;i<=n;i++)
{
int l=i,r=i+x-1;
if(r>n) continue;
int temp1=s[r]-s[l-1];
if(temp1==x) return true;
if(temp1==x-1)
{
int temp2=s[l-1];
int temp3=s[n]-s[r];
if(temp2||temp3) return true;
}
}
return false;
}
int main(void)
{
cin>>n>>a;
a="0"+a;
for(int i=1;i<+n;i++)
{
s[i]=s[i-1];
if(a[i]=='0') s[i]++;
}
int l=0,r=n;
while(l<r)
{
int mid=(l+r+1)/2;
if(check(mid)) l=mid;
else r=mid-1;
}
cout<<l;
return 0;
}
强迫症
重复的数和一个最大的数结合,一定可以构造一个不重复的数,一直这样。
故结果就是重复数的累加和,就是操作次数。
#include<bits/stdc++.h>
using namespace std;
int n,x,cnt;
map<int,int>mp;
int main(void)
{
cin>>n;
while(n--)
{
cin>>x;
if(mp.count(x)) cnt++;
mp[x]++;
}
cout<<cnt;
return 0;
}