A. Winner
题目地址:http://codeforces.com/contest/2/problem/A
题目大意:给出每一次比赛的得分情况,问最后得分最高的人。若最后分数同样,则输出分数同样的人中第一个分数不小于最后最高分数的人。
算法讨论:用STL中的map和set维护就可以。
Code:
#include <iostream>
#include <map>
#include <set>
#include <string>
#define N 1000
using namespace std;
int n,Max,score[N+10];
string name[N+10];
set<string> Set;
map<string,int> sum;
int main(){
cin>>n;
for (int i=1;i<=n;++i){
cin>>name[i]>>score[i];
sum[name[i]]+=score[i];
}
for (map<string,int>::iterator i=sum.begin();i!=sum.end();++i)
if (i->second>Max) Max=i->second;
for (map<string,int>::iterator i=sum.begin();i!=sum.end();++i)
if (i->second==Max) Set.insert(i->first);
sum.clear();
for (int i=1;i<=n;++i)
if (Set.count(name[i])){
sum[name[i]]+=score[i];
if (sum[name[i]]>=Max){
cout<<name[i]<<endl;
return 0;
}
}
}
B. The least round way
题目地址:http://codeforces.com/contest/2/problem/B
题目大意:给出一个矩阵,求从左上角到右下角的一条路径,使得路径上的数的乘积后的0最少。
算法讨论:
DP之。
分别求解从左上角到某一点的乘积中2的个数和5的个数,则0的个数为2的个数和5的个数中的较小值。
须要注意的是含0的情况。方法是读入的时候把0变成10,DP之,若答案大于1则使路径经过0就可以。
Code:
#include <cstdio>
#include <algorithm>
#include <stack>
#define N 1000
#define oo 0x7f7f7f7f
using namespace std;
int n,x,y,a[N+10][N+10],cnt[N+10][N+10][2],dp[N+10][N+10][2];
bool f;
stack<char> S;
int main(){
scanf("%d",&n);
for (int i=0;i<=n;++i)
for (int j=0;j<=n;++j) dp[i][j][0]=dp[i][j][1]=oo;
for (int i=1;i<=n;++i)
for (int j=1;j<=n;++j){
scanf("%d",&a[i][j]);
if (!a[i][j]) f=1,x=i,y=j,a[i][j]=10;
for (int t=a[i][j];t%2==0;t/=2,cnt[i][j][0]++);
for (int t=a[i][j];t%5==0;t/=5,cnt[i][j][1]++);
}
dp[1][1][0]=cnt[1][1][0];
dp[1][1][1]=cnt[1][1][1];
for (int i=1;i<=n;++i)
for (int j=1;j<=n;++j){
if (i==1 && j==1) continue;
dp[i][j][0]=min(dp[i-1][j][0],dp[i][j-1][0])+cnt[i][j][0];
dp[i][j][1]=min(dp[i-1][j][1],dp[i][j-1][1])+cnt[i][j][1];
}
if (f && min(dp[n][n][0],dp[n][n][1])>1){
printf("1\n");
for (int i=1;i<x;++i) printf("D");
for (int i=1;i<y;++i) printf("R");
for (int i=x;i<n;++i) printf("D");
for (int i=y;i<n;++i) printf("R");
return 0;
}
printf("%d\n",min(dp[n][n][0],dp[n][n][1]));
if (dp[n][n][0]<dp[n][n][1]){
int i=n,j=n;
do{
if (i>1 && dp[i][j][0]==dp[i-1][j][0]+cnt[i][j][0]) i--,S.push('D');
else if (j>1) j--,S.push('R');
}while (i!=1 || j!=1);
}
else{
int i=n,j=n;
do{
if (i>1 && dp[i][j][1]==dp[i-1][j][1]+cnt[i][j][1]) i--,S.push('D');
else if (j>1) j--,S.push('R');
}while (i!=1 || j!=1);
}
while (!S.empty()) printf("%c",S.top()),S.pop();
puts("");
return 0;
}
C. Commentator problem
题目地址:http://codeforces.com/contest/2/problem/C
题目大意:给三个圆(互不包括),求一个点,使得这个点看三个圆的视角同样。
算法讨论:模拟退火。
初始状态为三个圆心的中心,估价函数为三个视角的一半的正弦值的平方和。
Code:
#include <cstdio>
#include <cmath>
#define N 300000
#define eps 1e-20
using namespace std;
int xa,ya,ra,xb,yb,rb,xc,yc,rc;
double x,y,v,delta;
const int dx[]={0,0,1,-1},dy[]={1,-1,0,0};
inline double sqr(double x){
return x*x;
}
inline double dist(double x1,double y1,double x2,double y2){
return sqrt(sqr(x1-x2)+sqr(y1-y2));
}
inline double value(double x,double y){
double a1=ra/dist(x,y,xa,ya),a2=rb/dist(x,y,xb,yb),a3=rc/dist(x,y,xc,yc);
return sqr(a1-a2)+sqr(a2-a3)+sqr(a1-a3);
}
int main(){
scanf("%d%d%d",&xa,&ya,&ra);
scanf("%d%d%d",&xb,&yb,&rb);
scanf("%d%d%d",&xc,&yc,&rc);
x=(double)(xa+xb+xc)/3;
y=(double)(ya+yb+yc)/3;
v=value(x,y);
delta=1;
for (int i=0;i<N && v>eps;++i){
bool f=0;
for (int j=0;j<4;++j){
double xx=x+delta*dx[j],yy=y+delta*dy[j],vv;
if ((vv=value(xx,yy))<v) v=vv,x=xx,y=yy,f=1;
}
if (!f) delta*=.5;
}
if (value(x,y)<=eps) printf("%0.5lf %0.5lf\n",x,y);
return 0;
}
By Charlie Pan
Mar 4,2014
A. Winner
题目地址:http://codeforces.com/contest/2/problem/A
题目大意:给出每一次比赛的得分情况,问最后得分最高的人。若最后分数同样,则输出分数同样的人中第一个分数不小于最后最高分数的人。
算法讨论:用STL中的map和set维护就可以。
Code:
#include <iostream>
#include <map>
#include <set>
#include <string>
#define N 1000
using namespace std;
int n,Max,score[N+10];
string name[N+10];
set<string> Set;
map<string,int> sum;
int main(){
cin>>n;
for (int i=1;i<=n;++i){
cin>>name[i]>>score[i];
sum[name[i]]+=score[i];
}
for (map<string,int>::iterator i=sum.begin();i!=sum.end();++i)
if (i->second>Max) Max=i->second;
for (map<string,int>::iterator i=sum.begin();i!=sum.end();++i)
if (i->second==Max) Set.insert(i->first);
sum.clear();
for (int i=1;i<=n;++i)
if (Set.count(name[i])){
sum[name[i]]+=score[i];
if (sum[name[i]]>=Max){
cout<<name[i]<<endl;
return 0;
}
}
}
B. The least round way
题目地址:http://codeforces.com/contest/2/problem/B
题目大意:给出一个矩阵,求从左上角到右下角的一条路径,使得路径上的数的乘积后的0最少。
算法讨论:
DP之。
分别求解从左上角到某一点的乘积中2的个数和5的个数,则0的个数为2的个数和5的个数中的较小值。
须要注意的是含0的情况。方法是读入的时候把0变成10,DP之,若答案大于1则使路径经过0就可以。
Code:
#include <cstdio>
#include <algorithm>
#include <stack>
#define N 1000
#define oo 0x7f7f7f7f
using namespace std;
int n,x,y,a[N+10][N+10],cnt[N+10][N+10][2],dp[N+10][N+10][2];
bool f;
stack<char> S;
int main(){
scanf("%d",&n);
for (int i=0;i<=n;++i)
for (int j=0;j<=n;++j) dp[i][j][0]=dp[i][j][1]=oo;
for (int i=1;i<=n;++i)
for (int j=1;j<=n;++j){
scanf("%d",&a[i][j]);
if (!a[i][j]) f=1,x=i,y=j,a[i][j]=10;
for (int t=a[i][j];t%2==0;t/=2,cnt[i][j][0]++);
for (int t=a[i][j];t%5==0;t/=5,cnt[i][j][1]++);
}
dp[1][1][0]=cnt[1][1][0];
dp[1][1][1]=cnt[1][1][1];
for (int i=1;i<=n;++i)
for (int j=1;j<=n;++j){
if (i==1 && j==1) continue;
dp[i][j][0]=min(dp[i-1][j][0],dp[i][j-1][0])+cnt[i][j][0];
dp[i][j][1]=min(dp[i-1][j][1],dp[i][j-1][1])+cnt[i][j][1];
}
if (f && min(dp[n][n][0],dp[n][n][1])>1){
printf("1\n");
for (int i=1;i<x;++i) printf("D");
for (int i=1;i<y;++i) printf("R");
for (int i=x;i<n;++i) printf("D");
for (int i=y;i<n;++i) printf("R");
return 0;
}
printf("%d\n",min(dp[n][n][0],dp[n][n][1]));
if (dp[n][n][0]<dp[n][n][1]){
int i=n,j=n;
do{
if (i>1 && dp[i][j][0]==dp[i-1][j][0]+cnt[i][j][0]) i--,S.push('D');
else if (j>1) j--,S.push('R');
}while (i!=1 || j!=1);
}
else{
int i=n,j=n;
do{
if (i>1 && dp[i][j][1]==dp[i-1][j][1]+cnt[i][j][1]) i--,S.push('D');
else if (j>1) j--,S.push('R');
}while (i!=1 || j!=1);
}
while (!S.empty()) printf("%c",S.top()),S.pop();
puts("");
return 0;
}
C. Commentator problem
题目地址:http://codeforces.com/contest/2/problem/C
题目大意:给三个圆(互不包括),求一个点,使得这个点看三个圆的视角同样。
算法讨论:模拟退火。
初始状态为三个圆心的中心,估价函数为三个视角的一半的正弦值的平方和。
Code:
#include <cstdio>
#include <cmath>
#define N 300000
#define eps 1e-20
using namespace std;
int xa,ya,ra,xb,yb,rb,xc,yc,rc;
double x,y,v,delta;
const int dx[]={0,0,1,-1},dy[]={1,-1,0,0};
inline double sqr(double x){
return x*x;
}
inline double dist(double x1,double y1,double x2,double y2){
return sqrt(sqr(x1-x2)+sqr(y1-y2));
}
inline double value(double x,double y){
double a1=ra/dist(x,y,xa,ya),a2=rb/dist(x,y,xb,yb),a3=rc/dist(x,y,xc,yc);
return sqr(a1-a2)+sqr(a2-a3)+sqr(a1-a3);
}
int main(){
scanf("%d%d%d",&xa,&ya,&ra);
scanf("%d%d%d",&xb,&yb,&rb);
scanf("%d%d%d",&xc,&yc,&rc);
x=(double)(xa+xb+xc)/3;
y=(double)(ya+yb+yc)/3;
v=value(x,y);
delta=1;
for (int i=0;i<N && v>eps;++i){
bool f=0;
for (int j=0;j<4;++j){
double xx=x+delta*dx[j],yy=y+delta*dy[j],vv;
if ((vv=value(xx,yy))<v) v=vv,x=xx,y=yy,f=1;
}
if (!f) delta*=.5;
}
if (value(x,y)<=eps) printf("%0.5lf %0.5lf\n",x,y);
return 0;
}
By Charlie Pan
Mar 4,2014