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
*/

 

posted @ 2012-05-17 05:51  Because Of You  Views(383)  Comments(0Edit  收藏  举报