2016-2017 CT S03E06: Codeforces Trainings Season 3 Episode 6
比赛连接:
http://codeforces.com/gym/101124/
代码地址
Problem A. The Baguette Master
题意
给你一个四边形,让你给这个四边形加上一个长度为2的框,问你这个框的最大的周长是多少。
题解
框最多就往上移动或者往下移动,那么2^4枚举一下,然后取一个最大值就好了。
不过我队友好像不是这样写的。。。
代码
#include <bits/stdc++.h>
using namespace std;
const double pi=acos(-1);
const double eps=1e-9;
int main()
{
double tha,thb,thc,thd,w,ab,bc,cd,da,ac,ans,AB,BC,CD,DA,AC,BD;
scanf("%lf%lf%lf%lf%lf%lf",&w,&ab,&bc,&cd,&da,&ac);
thb=acos((ab*ab+bc*bc-ac*ac)/(2.0*ab*bc));
thd=acos((cd*cd+da*da-ac*ac)/(2.0*cd*da));
tha=acos((ab*ab+ac*ac-bc*bc)/(2.0*ab*ac))+acos((da*da+ac*ac-cd*cd)/(2.0*da*ac));
thc=acos((bc*bc+ac*ac-ab*ab)/(2.0*bc*ac))+acos((cd*cd+ac*ac-da*da)/(2.0*cd*ac));
if(fabs(tha-pi)<eps)
{
BC=bc+(w*cos(thb)/sin(thb)+w*cos(thc)/sin(thc));
CD=cd+(w*cos(thc)/sin(thc)+w*cos(thd)/sin(thd));
BD=ab+da+(w*cos(thd)/sin(thd)+w*cos(thb)/sin(thb));
ans=CD+BD+BC+2.0*(w/sin(thb)+w/sin(thc)+w/sin(thd));
}
else if(fabs(thb-pi)<eps)
{
CD=cd+(w*cos(thc)/sin(thc)+w*cos(thd)/sin(thd));
DA=da+(w*cos(thd)/sin(thd)+w*cos(tha)/sin(tha));
AC=ab+bc+(w*cos(tha)/sin(tha)+w*cos(thc)/sin(thc));
ans=CD+DA+AC+2.0*(w/sin(tha)+w/sin(thc)+w/sin(thd));
}
else if(fabs(thc-pi)<eps)
{
AB=ab+(w*cos(tha)/sin(tha)+w*cos(thb)/sin(thb));
DA=da+(w*cos(thd)/sin(thd)+w*cos(tha)/sin(tha));
BD=bc+cd+(w*cos(thb)/sin(thb)+w*cos(thd)/sin(thd));
ans=AB+BD+DA+2.0*(w/sin(tha)+w/sin(thb)+w/sin(thd));
}
else if(fabs(thd-pi)<eps)
{
AB=ab+(w*cos(tha)/sin(tha)+w*cos(thb)/sin(thb));
BC=bc+(w*cos(thb)/sin(thb)+w*cos(thc)/sin(thc));
AC=cd+da+(w*cos(thc)/sin(thc)+w*cos(tha)/sin(tha));
ans=AB+BC+AC+2.0*(w/sin(tha)+w/sin(thb)+w/sin(thc));
}
else
{
AB=ab+(w*cos(tha)/sin(tha)+w*cos(thb)/sin(thb));
BC=bc+(w*cos(thb)/sin(thb)+w*cos(thc)/sin(thc));
CD=cd+(w*cos(thc)/sin(thc)+w*cos(thd)/sin(thd));
DA=da+(w*cos(thd)/sin(thd)+w*cos(tha)/sin(tha));
ans=AB+BC+CD+DA+2.0*(w/sin(tha)+w/sin(thb)+w/sin(thc)+w/sin(thd));
}
// cout<<tha<<" "<<thb<<" "<<thc<<" "<<thd<<endl;
// cout<<tha+thb+thc+thd<<endl;
printf("%.12f
",ans);
return 0;
}
Problem C. Old Chess Sets
题意
给你两个集合,问你这两个集合加起来,能不能构成国际象棋的32个棋子。
题解
签到题
代码
#include<bits/stdc++.h>
using namespace std;
int k1,k2;
int mp[2][35];
int num[35];
int getid(string s){
if(s=="black")return 0;
if(s=="white")return 1;
if(s=="king")return 0;
if(s=="queen")return 1;
if(s=="bishop")return 2;
if(s=="knight")return 3;
if(s=="rook")return 4;
if(s=="pawn")return 5;
}
vector<string>ans1,ans2;
int main()
{
num[0]=1,num[1]=1,num[2]=2,num[3]=2,num[4]=2,num[5]=8;
memset(mp,0,sizeof(mp));
scanf("%d%d",&k1,&k2);
for(int i=0;i<k1;i++){
string s1,s2;
cin>>s1>>s2;
mp[getid(s1)][getid(s2)]++;
}
int flag = 0;
for(int i=0;i<k2;i++){
string s1,s2;
cin>>s1>>s2;
if(mp[getid(s1)][getid(s2)]<num[getid(s2)])
{
mp[getid(s1)][getid(s2)]++;
ans1.push_back(s1);
ans2.push_back(s2);
}
}
if(ans1.size()+k1==32){
for(int i=0;i<ans1.size();i++)
cout<<ans1[i]<<" "<<ans2[i]<<endl;
}
else{
cout<<"impossible"<<endl;
}
}
Problem D. Checkmate with Bishop and Knight
题意
给你一个国际象棋的局势,问你应该下哪一步,才能将死对面。
题解
直接暴力枚举就好了
代码
#include<bits/stdc++.h>
using namespace std;
pair<int,int> pos(string s){
return make_pair(s[0]-'a',s[1]-'1');
}
pair<int,int> bishop,knight,wking,bking;
int mp[10][10];
int dkx[8]={1,-1,1,-1,1,-1,0,0},dky[8]={1,-1,-1,1,0,0,1,-1};
int dbx[4]={1,-1,1,-1},dby[4]={1,-1,-1,1};
int dnx[8]={1,-1,1,-1,2,-2,2,-2},dny[8]={2,-2,-2,2,1,-1,-1,1};
bool test(int x,int y)
{
for(int i=0;i<8;i++){
int nx=x+dkx[i];
int ny=y+dky[i];
if(nx<0||nx>=8)continue;
if(ny<0||ny>=8)continue;
if(mp[nx][ny]==1)return true;
}
for(int i=0;i<4;i++){
for(int j=0;j<8;j++){
int nx=x+dbx[i]*(j+1);
int ny=y+dby[i]*(j+1);
if(nx<0||nx>=8)continue;
if(ny<0||ny>=8)continue;
if(mp[nx][ny]==2)return true;
if(mp[nx][ny])break;
}
}
for(int i=0;i<8;i++){
int nx=x+dnx[i];
int ny=y+dny[i];
if(nx<0||nx>=8)continue;
if(ny<0||ny>=8)continue;
if(mp[nx][ny]==3)return true;
}
return false;
}
bool check()
{
if(!test(bking.first,bking.second))
return 0;
for(int i=0;i<8;i++){
int nx=bking.first+dkx[i];
int ny=bking.second+dky[i];
if(nx<0||nx>=8)continue;
if(ny<0||ny>=8)continue;
if(!test(nx,ny))
return 0;
}
return 1;
}
int main()
{
string s;
cin>>s;wking=pos(s),mp[wking.first][wking.second]=1;
cin>>s;bishop=pos(s),mp[bishop.first][bishop.second]=2;
cin>>s;knight=pos(s),mp[knight.first][knight.second]=3;
cin>>s;bking=pos(s),mp[bking.first][bking.second]=4;
for(int i=0;i<8;i++){
int nx=knight.first+dnx[i];
int ny=knight.second+dny[i];
if(nx<0||nx>=8)continue;
if(ny<0||ny>=8)continue;
if(mp[nx][ny])continue;
mp[nx][ny]=3;
mp[knight.first][knight.second]=0;
knight=make_pair(nx,ny);
if(check()){
printf("N%c%c
",'a'+nx,'1'+ny);
return 0;
}
mp[nx][ny]=0;
knight=make_pair(nx-dnx[i],ny-dny[i]);
mp[knight.first][knight.second]=3;
}
for(int i=0;i<8;i++){
int nx=wking.first+dkx[i];
int ny=wking.second+dky[i];
if(nx<0||nx>=8)continue;
if(ny<0||ny>=8)continue;
if(mp[nx][ny])continue;
int ff=0;
for(int j=0;j<8;j++){
int nnx=nx+dkx[j];
int nny=ny+dky[j];
if(nnx<0||nnx>=8)continue;
if(nny<0||nny>=8)continue;
if(mp[nnx][nny]==4)ff=1;
}
if(ff)continue;
mp[nx][ny]=1;
mp[wking.first][wking.second]=0;
wking=make_pair(nx,ny);
if(check()){
printf("K%c%c
",'a'+nx,'1'+ny);
return 0;
}
mp[nx][ny]=0;
wking=make_pair(nx-dkx[i],ny-dky[i]);
mp[wking.first][wking.second]=1;
}
for(int i=0;i<4;i++){
for(int j=0;j<8;j++){
int nx=bishop.first+dbx[i]*(j+1);
int ny=bishop.second+dby[i]*(j+1);
if(nx<0||nx>=8)continue;
if(ny<0||ny>=8)continue;
if(mp[nx][ny])break;
mp[nx][ny]=2;
mp[bishop.first][bishop.second]=0;
bishop=make_pair(nx,ny);
if(check()){
printf("B%c%c
",'a'+nx,'1'+ny);
return 0;
}
mp[nx][ny]=0;
bishop=make_pair(nx-dbx[i]*(j+1),ny-dby[i]*(j+1));
mp[bishop.first][bishop.second]=2;
}
}
cout<<"impossible"<<endl;
}
Problem H. Kids’ Play
题意
给你一个有向图图,n点n边,点的度数小于等于2,每个点都在环上
然后Q次查询,每次查询从一个点开始,问这个点跑k步之后在哪个点上。
题解
处理出每个环,然后对于每一个点都倍增处理这个点走2^k步之后在哪儿。
然后暴力去搞一搞就好了
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+7;
vector<int> E[maxn],cir[maxn];
int vis[maxn],p[maxn][2],n,m,cnt,step[maxn][20],be[maxn],two[maxn];
void dfs(int x)
{
if(vis[x])return;
vis[x]=1;
cir[cnt].push_back(x);
be[x]=cnt;
for(int i=0;i<E[x].size();i++){
step[x][0]=E[x][i];
dfs(E[x][i]);
}
}
int main()
{
two[0]=1;
for(int i=1;i<20;i++)
two[i]=two[i-1]*2;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
int a,b;
scanf("%d%d",&a,&b);
p[a][0]=i,p[b][1]=i;
step[i][0]=i;
}
for(int i=1;i<=n;i++)
E[p[i][1]].push_back(p[i][0]);
for(int i=1;i<=n;i++)
if(!vis[i])
{
cnt++;
dfs(i);
}
for(int j=1;j<20;j++)
for(int i=1;i<=n;i++)
step[i][j]=step[step[i][j-1]][j-1];
for(int i=1;i<=m;i++){
int a,b;
scanf("%d%d",&a,&b);
b%=cir[be[a]].size();
int now = a;
for(int j=19;j>=0;j--)
{
if(b>=two[j])
{
now=step[now][j];
b-=two[j];
}
}
cout<<now<<endl;
}
}
Problem I. Odd Factor (64 MB ML!)
题意
给你一个无向图,让你删除一些边,使得每个点的度数都是奇数
题解
先找一棵树出来,然后自下而上,如果这个点度数为偶数,就删除这个点与根相连的边就好了
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6+7;
vector<int> E[maxn];
vector<int> id[maxn];
vector<int>ans1,ans2,ans3;
int vis[maxn];
int V[maxn],d[maxn],fa[maxn],p[maxn];
int n,m,flag=0;
void dfs(int x)
{
vis[x]=1;
for(int i=0;i<E[x].size();i++){
if(vis[E[x][i]])continue;
d[E[x][i]]++;
d[x]++;
ans1.push_back(x);
ans2.push_back(E[x][i]);
ans3.push_back(1);
p[E[x][i]]=ans1.size()-1;
dfs(E[x][i]);
}
if(p[x]==-1){
if(d[x]%2==0)flag=1;
}else{
if(d[x]%2==0){
d[x]--;
d[ans1[p[x]]]--;
ans3[p[x]]=0;
}
}
}
int main()
{
memset(p,-1,sizeof(p));
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++){
int a,b;
scanf("%d%d",&a,&b);
E[a].push_back(b);
E[b].push_back(a);
id[a].push_back(i);
id[b].push_back(i);
}
for(int i=1;i<=n;i++)
if(!vis[i])dfs(i);
if(flag){
cout<<"-1"<<endl;
return 0;
}
int tmp = 0;
for(int i=0;i<ans1.size();i++)
if(ans3[i])tmp++;
cout<<tmp<<endl;
for(int i=0;i<ans1.size();i++)
if(ans3[i]==1)
cout<<ans1[i]<<" "<<ans2[i]<<endl;
return 0;
}
Problem K. Average Speed
题意
给你每个时间段汽车的速度,多次查询汽车在某个时间一共跑了多远
题解
签到题,水题
代码
#include<bits/stdc++.h>
using namespace std;
string s;
double gettime(string s)
{
double h = (s[0]-'0')*10+s[1]-'0';
double m = (s[3]-'0')*10+s[4]-'0';
double ss = (s[6]-'0')*10+s[7]-'0';
return h+m/60.0+ss/3600.0;
}
int main()
{
double now = 0;
double lasttime = 0;
double lastspeed = 0;
while(getline(cin,s))
{
if(s.size()>8){
double time = gettime(s);
now+=(time-lasttime)*lastspeed;
lastspeed=0;
for(int i=9;i<s.size();i++)
lastspeed=lastspeed*10+s[i]-'0';
lasttime=time;
}
else{
double time = gettime(s);
cout<<s<<" ";
printf("%.2f km
",(time-lasttime)*lastspeed+now);
}
}
}
Problem L. Subway
题意
给你一个二维平面,上面有地铁,地铁的速度和人的速度给你
现在让你从起点到家,问你怎么走最快。
题解
把直接走路和地铁的边都扔进邻接矩阵里面,然后去跑floyd就好了
代码
#include<bits/stdc++.h>
using namespace std;
double x1,y1,x2,y2;
double lx,ly,nx,ny;
int cnt=0;
double X[250],Y[250];
double len[250];
double dp[250][250];
double dis(double x,double y,double xx,double yy){
return sqrt((x-xx)*(x-xx)+(y-yy)*(y-yy));
}
int main()
{
for(int i=0;i<250;i++)
for(int j=0;j<250;j++)
if(i==j)dp[i][j]=0;
else dp[i][j]=1e9;
cin>>x1>>y1>>x2>>y2;
cnt++;X[0]=x1,Y[0]=y1;
while(cin>>nx>>ny){
int st=cnt;
len[cnt]=0;
X[cnt]=nx,Y[cnt]=ny;
for(int i=0;i<cnt;i++)
{
dp[cnt][i]=min(dp[cnt][i],dis(nx,ny,X[i],Y[i])/1000.0*6);
dp[i][cnt]=min(dp[i][cnt],dis(nx,ny,X[i],Y[i])/1000.0*6);
}
cnt++;
while(cin>>lx>>ly){
if(lx==-1&&ly==-1)break;
swap(lx,nx);
swap(ly,ny);
len[cnt]=dis(lx,ly,nx,ny)+len[cnt-1];
X[cnt]=nx,Y[cnt]=ny;
for(int i=0;i<cnt;i++)
{
dp[cnt][i]=min(dp[cnt][i],dis(nx,ny,X[i],Y[i])/1000.0*6);
dp[i][cnt]=min(dp[i][cnt],dis(nx,ny,X[i],Y[i])/1000.0*6);
}
for(int i=st;i<cnt;i++)
{
dp[cnt][i]=min(dp[cnt][i],(len[cnt]-len[i])/4000.0*6);
dp[i][cnt]=min(dp[i][cnt],(len[cnt]-len[i])/4000.0*6);
}
cnt++;
}
}
X[cnt]=x2,Y[cnt]=y2;
for(int i=0;i<=cnt;i++){
for(int j=0;j<=cnt;j++){
if(i==j)dp[i][j]=0;
else dp[i][j]=min(dp[i][j],dis(X[i],Y[i],X[j],Y[j])/1000.0*6);
}
}
for(int k=0;k<=cnt;k++){
for(int j=0;j<=cnt;j++){
for(int i=0;i<=cnt;i++)
dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]);
}
}
printf("%.0f
",dp[0][cnt]);
}
Problem M. A multiplication game
题意
一开始数是1,两人在玩博弈论,该一个人的时候,就让他乘上2~9中的一个数,如果这个数大于等于p就胜利。
题解
直接dfs搜吧,感觉上状态很小的样子
代码
#include<bits/stdc++.h>
using namespace std;
long long n;
map<long long,int>H;
int dfs(long long o){
if(H[o])return H[o]-1;
if(o>=n)return 1;
int flag = 1;
for(int i=2;i<=9;i++)
if(dfs(o*1ll*i))
flag=0;
H[o]=flag+1;
return flag;
}
int main()
{
while(cin>>n)
{
if(n==1){
cout<<"Stan wins."<<endl;
continue;
}
H.clear();
int o=dfs(1);
if(o==0)cout<<"Stan wins."<<endl;
else cout<<"Ollie wins."<<endl;
}
}