您的位置:首页 > 其它

2017计蒜之道程序设计大赛初赛第三场题解

2017-05-22 17:11 267 查看
比赛链接

题目可以在比赛的题目列表中查看


腾讯课堂的物理实验

在腾讯课堂的物理课上,进行了一个有趣的物理实验。

在一个长度为 LL 米的光滑轨道上,小车
A 在 00 时刻以1m/s 的速度从左端出发向右运动,小车
B 在 tt 时刻以 1m/s 的速度从右端出发向左运动,两个小车的质量相等。假设所有碰撞都是弹性碰撞,也就是当两个小车相向碰撞时,他们各自会以原来的速度向相反的方向运动;小车和轨道两端发生碰撞时,小车会以原速度向反方向运动。

试求出 TT 时刻的时候,两个小车相距多远。

输入格式

输入三个整数 L(1 \le L \le 1000),L(1≤L≤1000), t(0
\le t \le 1000),t(0≤t≤1000), T(t
\le T \le 1000)T(t≤T≤1000)。

输出格式

输出 TT 时刻两车之间的距离。

样例输入1

10 4 7

样例输出1

0

样例输入2

8 3 9

样例输出2

5

命题人:镇高红

碰撞其实可以视为相互穿越,那么两车其实可以视为没有任何相互影响,然后单独模拟即可。“两个小球相撞后沿相反方向走,就可以看成是两个小球互相瞅了一眼,谁都不理谁,擦肩而过。”

白书序言蚂蚁问题

#include<iostream>
#include<cstdio>
#include<cmath>
#include<vector>
#include<queue>
#include<fstream>
#include<string.h>
using namespace std;
const int INF=0x3f3f3f3f;
const int MAXN=10000;

int main()
{
int L,t,T;
while(cin>>L>>t>>T)
{
int time=0;
int p1=0,p2=L;
int d1=1,d2=-1;
while(time!=T)
{
time++;
bool flag1=false,flag2=false;

if(p1==0&&d1==-1)
{
d1=-d1;
p1=p1+d1;
flag1=true;
}
else if(p1==L&&d1==1)
{
d1=-d1;
p1=p1+d1;
flag1=true;
}
if(p2==0&&d2==-1&&time>t)
{
d2=-d2;
p2=p2+d2;
flag2=true;
}
else if(p2==L&&d2==1&&time>t)
{
d2=-d2;
p2=p2+d2;
flag2=true;
}

if(p1==p2&&time>t&&flag1==false)
{
d1=-d1;d2=-d2;
p1=p1+d1;
p2=p2+d2;
}
else if(p1+d1*(0.5)==p2+d2*(0.5)&&time>t&&flag1==false)
{
d1=-d1;d2=-d2;
}
else
{
if(flag1==false)p1=p1+d1;
if(time>t&&flag2==false)
p2=p2+d2;
}
//cout<<time<<": p1: "<<p1<<" "<<"p2: "<<p2<<" d1:"<<d1<<" "<<"d2: "<<d2<<endl;
}
cout<<abs(p1-p2)<<endl;
}
return 0;
}AC版本2:

#include<iostream>
#include<string.h>
#include<stdio.h>
using namespace std;

int t,l,n;

int main()
{
cin>>l>>t>>n;
int x=n%(2*l);
if(x>l)x=2*l-x;
int y=(n-t)%(2*l);
if(y>l)y=2*l-y;
y=l-y;
if(x-y>0)cout<<x-y;
else cout<<y-x;
}


腾讯狼人杀

命题人:徐浩


简单版本

可以采用二进制枚举的方式直接得到答案。


分析:

也没什么好说的,数据很小,只有20个人,暴力枚举,220种组合方式,在剪枝掉不可能出现的方式,也就是必须选择的村民没被选中的情况。我是在dfs的过程中的每一层,都保持对总战斗力sum动态维护;而不是每一次组合方式确定之后再单独算一遍这种组合方式的性价比。如果那样算应该会超时我猜。
#include<iostream>
#include<stdio.h>
#include<string.h>

using namespace std;
int map[30][30]={0};
int vis[30]={0};
int in[30]={0};
int n,m;
int a,b,w;
int sum=0;
int chose=0;
double best=0;
void dfs(int x)//决定第x个是不是选
{
if(x==n+1)
{
double o=(double)(sum)/(double)(chose*(2*n-chose));
//cout<<o<<" "<<chose<<in[1]<<endl;
if(best<o)best=o;
return;
}
for(int i=0;i<=1;i++)
{
if(vis[x]==1&&i==0)continue;
in[x]=i;
if(in[x]==1)
{
for(int i=1;i<x;i++)
{
if(in[i]==1)sum+=map[i][x];
}
chose++;
}
dfs(x+1);
if(in[x]==1)
{
for(int i=1;i<x;i++)
{
if(in[i]==1)sum-=map[i][x];
}
in[x]=0;
chose--;
}
}
}

int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&a,&b,&w);
map[a][b]=w;
map[b][a]=w;
}
int k=0;//有k个可供选择的人
for(int i=1;i<=n;i++)
{
scanf("%d",&a);
if(a==1)
{
//k++;
vis[i]=1;
}
}
dfs(1);
printf("%.4lf",best);
}



中等版本

假设答案为 ansans,构造函数 F=|E|
- ans \times k \times (2n-k)F=∣E∣−ans×k×(2n−k),当 ansans 过大时, F
\le 0F≤0;当 ansans 过小时,F>0F>0,所以我们可以二分这个 ansans。同时,我们观察到 ans
\times k \times (2n-k)ans×k×(2n−k) 可以写成 k^2ans-2nk
\times ansk​2​​ans−2nk×ans,可以写成 \frac{k(k-1)}{2}\times
2ans - (2n-1)k \times ans​2​​k(k−1)​​×2ans−(2n−1)k×ans,所以我们可以把每个权点看成 (2n-1)\times
ans(2n−1)×ans,边权都加上 2ans2ans。就变成了最基础的最大密度子图。


困难版本

对于困难版本,我们继续优化最大密度子图的建图方式,具体可以参考胡伯涛的论文《最小割模型在信息学竞赛中的应用》。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: