题目链接点击打开链接
B. Best Relay Team
直接模拟,按照后三棒成绩排序然后枚举第一棒的人选。
#include<bits/stdc++.h>
#define maxn 1050
#define INF 0x3f3f3f3f
#define eps 1e-8
using namespace std;
typedef long long ll;
int n;
struct node
{
char name[maxn];
double x,y;
}e[maxn];
bool cmp(node a,node b)
{
return a.y<b.y;
}
int main()
{
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%s%lf%lf",e[i].name,&e[i].x,&e[i].y);
}
sort(e,e+n,cmp);
int k;
double ans=1.0*INF;
for(int i=0;i<n;i++)
{
double sum=e[i].x;
int num=0;
for(int j=0;j<n;j++)
{
if(i==j)continue;
sum+=e[j].y;
num++;
if(num==3)break;
}
if(sum<ans)
{
ans=sum;
k=i;
}
}
printf("%lf\n%s\n",ans,e[k].name);
int num=0;
for(int i=0;i<n;i++)
{
if(i==k)continue;
printf("%s\n",e[i].name);
num++;
if(num==3)break;
}
return 0;
}
D. Distinctive Character
求一个串使得其与给定各串的最大相似度最小。
一个串与本身的相似度最大,改变任意一位数可使其与原串的相似度-1。从给定的所有串出发bfs,这样可以保证每个新串在被扩展到时,它和扩展得到它的子串之间取到的是各串的最大相似度,且这个值即子母串之间的距离最小,这样就保证了最大相似度最小。最后遍历一遍扩展到的串找出最底层的任意一个串即可。时间复杂度O(2^k)。
#include<bits/stdc++.h>
#define maxn 35
#define INF 0x3f3f3f3f
#define eps 1e-8
using namespace std;
typedef long long ll;
int n,m;
char s[maxn];
int dis[1<<20];
queue<int>q;
int main()
{
scanf("%d%d",&n,&m);
memset(dis,-1,sizeof(dis));
for(int i=0;i<n;i++)
{
scanf("%s",s);
int tmp=0;
for(int j=m-1;j>=0;j--)
{
tmp*=2;
tmp+=(s[j]-'0');
}
dis[tmp]=0;
q.push(tmp);
}
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=0;i<m;i++)
{
int v=u^(1<<i);
if(dis[v]==-1)
{
dis[v]=dis[u]+1;
q.push(v);
}
}
}
int ans=0,maxx=0;
for(int i=0;i<(1<<20);i++)
{
if(maxx<dis[i])
{
maxx=dis[i];
ans=i;
}
}
for(int i=0;i<m;i++)
{
printf("%d",ans%2);
ans/=2;
}
printf("\n");
return 0;
}
E. Emptying the Baltic
给定地形,求给定点处可有多少水流入。
从给定点向外bfs,保存每个点可外流的最大水深。扩展至一个新的点时,新点的最大外流量为前序点最大外流量与新点水深的较小值。最后将每个能扩展到的点的最大外流量相加即为答案。在bfs中使用优先队列,以保证每次拿出的状态都为前序点的最大外流量。
#include<bits/stdc++.h>
#define maxn 505
#define INF 0x3f3f3f3f
#define eps 1e-8
using namespace std;
typedef long long ll;
int n,m,sx,sy;
int ans[maxn][maxn];
int maze[maxn][maxn];
bool vis[maxn][maxn];
int pos[8][2]={1,0,0,1,-1,0,0,-1,1,1,1,-1,-1,-1,-1,1};
struct node
{
int x,y;
int h;
bool friend operator < (const node a,const node b)
{
return a.h>b.h;
}
};
bool judge(int x,int y)
{
if(x>=1&&y>=1&&x<=n&&y<=m&&!vis[x][y])
return true;
return false;
}
void bfs(int sx,int sy)
{
node st,now,nxt;
priority_queue<node>q;
st.x=sx,st.y=sy,st.h=maze[sx][sy];
ans[sx][sy]=maze[sx][sy];
vis[sx][sy]=1;
q.push(st);
while(!q.empty())
{
now=q.top();
q.pop();
for(int i=0;i<8;i++)
{
int fx=now.x+pos[i][0];
int fy=now.y+pos[i][1];
if(judge(fx,fy))
{
vis[fx][fy]=1;
nxt.x=fx,nxt.y=fy;
nxt.h=ans[fx][fy]=max(maze[fx][fy],now.h);
q.push(nxt);
}
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
scanf("%d",&maze[i][j]);
if(maze[i][j]>=0)vis[i][j]=1;
}
}
scanf("%d%d",&sx,&sy);
bfs(sx,sy);
ll sum=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(vis[i][j])
sum+=(-1LL*ans[i][j]);
}
}
printf("%I64d\n",sum);
return 0;
}
G. Galactic Collegiate Programming Contest
模拟一个榜单,每次查询队伍1的名次。
维护所有名次在队伍1之前的队伍。如果其他队过题则更新,如果是队伍1过题就将此时在队伍1之后的队伍全部删掉。这种维护需要使用平衡树,这里选用STL中基于平衡树原理实现的multiset可以解决,每次查询输出的是multiset的大小。需要注意队伍1不在榜单时结果+1,以及队伍1和其他队伍并列时只保留队伍1。
#include<bits/stdc++.h>
#define maxn 100050
#define INF 0x3f3f3f3f
#define eps 1e-8
using namespace std;
typedef long long ll;
int n,m,x,y;
struct node
{
int num;
int sum;
int id;
bool friend operator < (const node a,const node b)
{
if(a.num!=b.num)return a.num>b.num;
else if(a.sum!=b.sum)return a.sum<b.sum;
else return a.id<b.id;
}
}e[maxn];
multiset<node>ans;
multiset<node>::iterator it;
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
e[i].num=e[i].sum=0,e[i].id=i;
for(int i=0;i<m;i++)
{
scanf("%d%d",&x,&y);
if(ans.count(e[x]))
ans.erase(ans.find(e[x]));
e[x].num++;
e[x].sum+=y;
ans.insert(e[x]);
if(ans.count(e[1]))
{
while(!ans.empty()&&e[1]<*(--ans.end()))
ans.erase(--ans.end());
printf("%d\n",ans.size());
}
else printf("%d\n",ans.size()+1);
}
return 0;
}
I. Import Spaghetti
用Floyd算法求有向图中的最小环并输出其中一个最小环。
#include<bits/stdc++.h>
#define maxn 505
#define INF 0x3f3f3f3f
#define eps 1e-8
using namespace std;
typedef long long ll;
int n,m,minn;
int x,y,z;
string s;
map<string,int>mo;
map<int,string>om;
char t[maxn];
int fa[maxn][maxn],dis[maxn][maxn];
int maze[maxn][maxn],path[maxn];
void floyd()
{
minn=INF;
for(int k=1;k<=n;k++)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(dis[i][j]==INF||maze[j][k]==INF||maze[k][i]==INF)
continue;
if(dis[i][j]+maze[j][k]+maze[k][i]<minn)
{
minn=dis[i][j]+maze[j][k]+maze[k][i];
x=i;
y=j;
z=k;
}
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(dis[i][k]==INF||dis[k][j]==INF)
continue;
if(dis[i][j]>dis[i][k]+dis[k][j])
{
dis[i][j]=dis[i][k]+dis[k][j];
fa[i][j]=k;
}
}
}
}
}
void print_path(int u,int v)
{
if(u==v)return;
if(fa[u][v]==0)
cout<<om[v]<<" ";
else
{
print_path(u,fa[u][v]);
print_path(fa[u][v],v);
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
cin>>s;
mo[s]=i;
om[i]=s;
}
for(int i=0;i<=n;i++)
{
for(int j=0;j<=n;j++)
maze[i][j]=dis[i][j]=INF;
}
memset(fa,0,sizeof(fa));
for(int i=1;i<=n;i++)
{
cin>>s;
int u=mo[s];
scanf("%d",&m);
for(int j=0;j<m;j++)
{
scanf("%s",t);
int v,pre=u;
string a;
while(getchar()!='\n')
{
cin>>a;
if(a[a.length()-1]==',')
a.erase(a.end()-1);
v=mo[a];
//cout<<pre<<" "<<v<<endl;
maze[pre][v]=dis[pre][v]=1;
pre=v;
}
}
}
for(int i=1;i<=n;i++)
{
if(maze[i][i]==1)
{
cout<<om[i]<<endl;
return 0;
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(maze[i][j]==1&&maze[j][i]==1)
{
cout<<om[i]<<" "<<om[j]<<endl;
return 0;
}
}
}
floyd();
if(minn==INF)printf("SHIP IT\n");
else
{
cout<<om[x]<<" ";
print_path(x,y);
cout<<om[z]<<endl;
}
return 0;
}
J. Judging Moose
直接按照题意模拟。
#include<bits/stdc++.h>
#define maxn 1050
#define INF 0x3f3f3f3f
#define eps 1e-8
using namespace std;
typedef long long ll;
int a,b;
int main()
{
scanf("%d%d",&a,&b);
if(a==0&&b==0)printf("Not a moose\n");
else if(a==b)printf("Even %d\n",a*2);
else printf("Odd %d\n",max(a,b)*2);
return 0;
}
K. Kayaking Trip
3种人两两搭配,每对有一个以某种方式计算出的权值,求最小权值的最大值。
二分答案,在每次验证时贪心地去取,在6种可能方案中取权值最小的合法方案,若每一对都能取出合法方案则该答案合法。
#include<bits/stdc++.h>
#define maxn 100050
#define INF 0x3f3f3f3f
#define eps 1e-8
using namespace std;
typedef long long ll;
int num[3],val[3];
int m,cnt,cur[3];
int w[maxn];
struct node
{
int x,y;
int sum;
}e[15];
bool judge(int x)
{
for(int i=0;i<3;i++)cur[i]=num[i];
for(int i=0;i<m;i++)
{
bool flag=0;
for(int j=0;j<cnt;j++)
{
int p=e[j].x,q=e[j].y;
if(cur[p]==0||cur[q]==0||w[i]*e[j].sum<x)continue;
if(p==q&&cur[q]<2)continue;
cur[p]--,cur[q]--;
flag=1;
break;
}
if(!flag)return false;
}
return true;
}
int main()
{
for(int i=0;i<3;i++)scanf("%d",&num[i]);
for(int i=0;i<3;i++)scanf("%d",&val[i]);
m=(num[0]+num[1]+num[2])/2;
for(int i=0;i<m;i++)
scanf("%d",&w[i]);
sort(w,w+m);
cnt=0;
for(int i=0;i<3;i++)
{
for(int j=i;j<3;j++)
{
e[cnt].x=i,e[cnt].y=j;
e[cnt++].sum=val[i]+val[j];
}
}
int l=0,r=INF,ans;
while(l<=r)
{
int mid=(l+r)>>1;
if(judge(mid))
{
l=mid+1;
ans=mid;
}
else r=mid-1;
}
printf("%d\n",ans);
return 0;
}