codeforces 练习 ---- CF 24
A
给你一个环,环上的每条边都有一个方向,按某个方向(顺时针或逆时针)走一遍,把与行走的方向相反的边反向,并加上相应的费用,判断走哪个方向的费用比较少
直接dfs搞即可
View Code
#include<cstdio> #include<cstring> #include<vector> #include<algorithm> using namespace std; int out[110]; vector<int> edge[110]; int flag[110][110]; int mm[110][110]; int vis[110]; vector<pair<int,int> >rec; void dfs(int u,int fa) { vis[u]++;if(vis[u]==2) return ; for(int i=0;i<edge[u].size();i++) { int v=edge[u][i]; if(v==fa) continue; flag[u][v]=1; rec.push_back(make_pair(v,u)); dfs(v,u); return ; } } int main() { int n,i,j,k,a,b,c; while(scanf("%d",&n)!=EOF) { rec.clear(); for(i=0;i<=n;i++) edge[i].clear(); memset(out,0,sizeof(out)); memset(mm,0,sizeof(mm)); memset(flag,0,sizeof(flag)); memset(vis,0,sizeof(vis)); for(i=0;i<n;i++) { scanf("%d%d%d",&a,&b,&c); edge[a].push_back(b); edge[b].push_back(a); mm[b][a]=c; } dfs(1,0); int ans=0,tmp=0; for(i=0;i<rec.size();i++) ans+=mm[rec[i].second][rec[i].first]; for(i=0;i<rec.size();i++) tmp+=mm[rec[i].first][rec[i].second]; if(tmp<ans) ans=tmp; printf("%d\n",ans); } return 0; }
B
模拟题,写烦了,开始还由于数组开小了各种错
View Code
#pragma warning (disable : 4786) #include<cstdio> #include<cstring> #include<vector> #include<string> #include<map> #include<set> #include<iostream> #include<algorithm> using namespace std; map<string,int> mm; map<string,int> mp; set<string> ss; int pre[100]={25,18,15,12,10,8,6,4,2,1}; int fight[100][55]; struct node{ int p; string s1; int cnt[100]; }hehe[100]; int tot; int cmp(node a,node b){ for(int i=0;i<50;i++) if(a.cnt[i]!=b.cnt[i]) return a.cnt[i]>b.cnt[i]; } int cmp2(node a,node b){ if(a.p!=b.p) return a.p>b.p; for(int i=0;i<50;i++) if(a.cnt[i]!=b.cnt[i]) return a.cnt[i]>b.cnt[i]; } void gao(string s) { int num=0; hehe[tot].s1=s; int i,j,k; int id=mp[s]; for(i=0;i<50;i++) hehe[tot].cnt[num++]=fight[id][i]; tot++; } void gao2(string s) { int num=0; hehe[tot].s1=s; hehe[tot].p=mm[s]; int i,j,k; int id=mp[s]; for(i=0;i<50;i++) hehe[tot].cnt[num++]=fight[id][i]; tot++; } int main() { int n,i,j,k,a,b,c,m; string str;vector<string> re,xx; while(scanf("%d",&n)!=EOF) { tot=0; memset(fight,0,sizeof(fight));//fight[i][j] i获得第j名的次数 mm.clear(); ss.clear(); mp.clear(); int idx=0;int r; for(j=0;j<n;j++) { scanf("%d",&m); for(i=0;i<m;i++) { cin>>str; ss.insert(str); if(mp.find(str)==mp.end()) mp[str]=++idx; fight[mp[str]][i]++; if(i<10) mm[str]+=pre[i]; } } int Max=0; set<string>::iterator it; re.clear();xx.clear(); for(it=ss.begin();it!=ss.end();it++) { if(mm[*it]>=Max) { if(mm[*it]==Max) re.push_back(*it); else { re.clear(); re.push_back(*it); } Max=mm[*it]; } } for(i=0;i<re.size();i++) gao(re[i]); sort(hehe,hehe+tot,cmp); cout<<hehe[0].s1<<endl; Max=0; for(it=ss.begin();it!=ss.end();it++) { if(fight[mp[*it]][0]>=Max) { if(fight[mp[*it]][0]==Max) xx.push_back(*it); else { xx.clear(); xx.push_back(*it); } Max=fight[mp[*it]][0]; } } tot=0; for(i=0;i<xx.size();i++) gao2(xx[i]); sort(hehe,hehe+tot,cmp2); cout<<hehe[0].s1<<endl; } return 0; }
C
找规律,列出坐标转换的式子后发现2*n次变换回到原来的点
View Code
#include<cstdio> #include<cstring> int a[100010][2]; int main() { __int64 index; int n,i,j,k; while(scanf("%d%I64d",&n,&index)!=EOF) { __int64 x0,y0; scanf("%I64d%I64d",&x0,&y0); for(i=0;i<n;i++) scanf("%d%d",&a[i][0],&a[i][1]); int lim=index%(2*n);//printf("m=%d\n",lim); for(i=0;i<lim;i++) { x0=2*a[i%n][0]-x0; y0=2*a[i%n][1]-y0; } printf("%I64d %I64d\n",x0,y0); } return 0; }
D
DP求期望
每一个格子都相当于一个未知数,然后相邻的未知数间有某些对应关系,列出方程解出所有的未知数,
最后一行的未知数都已经求出来了zi,然后只需要一行一行往上推即可
有些人用迭代也过了,真心不懂,感觉也不太合理
View Code
/* x[0]=1+x[0]/3+x[1]/3+z[0]/3 xi=1+x[i]/4+x[i-1]/4+x[i+1]/4+z[i]/4; for i from 1 to m-2 x[m-1]=1+x[m-1]/3+x[m-2]/3+z[m-1]/3; 化简后: 系数 a b c : : : 2*x[0] - x[1] = z[0]+3;//边界 ...... -x[i-1] + 3*x[i] - x[i+1] = 4+z[i] 1<=i<=m-2 ..... -x[m-2] + 2*x[m-1] = 3+z[m-1]//边界 得出这个系数矩阵之后就是解一个 斜三角矩阵线性方程组 其实就是从上往下不断地迭代下来解方程组 一直迭代到最后就剩一个未知数了,然后可以反推回来所有的未知数 */ #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn = 1010; double a[maxn],b[maxn],c[maxn],d[maxn],X[maxn]; void solveMatrix (int n, double *a, double *b, double *c,double *x) { for (int i = 1; i < n; i++) { double m = a[i]/b[i-1]; b[i] = b[i] - m * c[i - 1]; x[i] -= m*x[i-1]; } x[n-1] = x[n-1]/b[n-1]; for (int i = n - 2; i >= 0; --i) x[i] = (x[i] - c[i] * x[i+1]) / b[i]; } int main() { int n,m,x,y,i,j; while(scanf("%d%d%d%d",&n,&m,&x,&y)!=EOF) { fill(d,d+m,0); for(i=n-1;i>=x;i--) { fill(a,a+m,-1); fill(b,b+m,3); fill(c,c+m,-1); a[0]=c[m-1]=0;b[0]--;b[m-1]--; for(j=0;j<m;j++) d[j]+=b[j]+1; solveMatrix(m,a,b,c,d); } printf("%.10lf\n",d[y-1]); } return 0; }
E
感觉最神奇的题,第三组数组本地死活跑不出来,可能精度要求太高的原因吧,但是给judge函数加了个inline就直接AC了,非常的不解
View Code
#include<cstdio> #include<cstring> #include<cmath> const double eps = 1e-12; const int maxn = 555555; int x[maxn],v[maxn]; inline int sgn(double x){ return fabs(x) < eps ? 0 : (x>0?1:-1); } inline bool intersect(double a,double b,double c,double d){ return (sgn(c-a)>=0 && sgn(b-c)>=0 || sgn(d-a)>=0 && sgn(b-d)>=0 || sgn(a-c)>=0 && sgn(d-b)>=0 ); } int n; inline bool judge(double mid){//加了inline之后就不超时了 int i,j; double l=-1e10,r=-1e10; bool flag=false; for(i=1;i<=n;i++){ if(v[i]>0){ if(sgn(x[i]+mid*v[i]-r)>0){ l=x[i]; r=x[i]+mid*v[i]; } flag = true; } else { if(!flag) continue; if(intersect(l,r,x[i]+v[i]*mid,x[i])) return true; } } return false; } inline bool judge2(double t) { double far = -1e20; for (int i = 0; i < n; i ++) { if (v[i] > 0) far = max(far, x[i]+v[i]*t); else if (x[i]+v[i]*t <= far) return true; } return false; } int main(){ int i,j; while(scanf("%d",&n)!=EOF){ int pre,now; bool flag=false; int cnt=0,re; for(i=1;i<=n;i++){ scanf("%d%d",&x[i],&v[i]); if(i==1) pre=v[i]>0?1:-1; now=v[i]>0?1:-1; if(now!=pre) { re=pre; cnt++; flag=true; } pre=now; } if(cnt==1&&re<0 || !flag){ puts("-1"); continue; } double l=0,r=1e10,mid; double best=-1; while(fabs(r-l)>=eps){ mid=0.5*(l+r); if(judge(mid)){ best=mid; r=mid; } else l=mid; } printf("%.10lf\n",best); } } /* 2 -1000000000 1 1000000000 -1 */