HCPC 2011 Spring Online Contest解题报告

来源:互联网 发布:python 基础教程怎么样 编辑:程序博客网 时间:2024/06/07 07:42
HCPC 2011 Spring Online Contest解题报告

A题 RPNF

悲了个催,这种题一直是令我纠结的一种题,表达式求值。。。应该找个时间把这类的正解学下,不能总是现场YY。。。一个堆栈操作的过程,

1.遇到字母直接输出

2.遇到运算符或者左括号op,从栈顶开始,依次与op比较,若优先级大于op,则出栈输出,直到栈为空或者栈顶操作符优先级小于op或者栈顶为'('然后op进栈

3.遇到')',一直出栈,直到栈顶为'('这样就把问题完美解决了代码:

#include <stdio .h>#include <ctype .h>#define N 300char st[N],stack[N];int priority(char op){    switch(op)    {        case '+':return 0;        case '-':return 1;        case '*':return 2;        case '/':return 3;        case '^':return 4;        default:return 5;    }}bool cmp(char op1,char op2){    return priority(op1)>=priority(op2);}int main(){    int t,i,top;    scanf("%d",&t);    while(t--)    {        scanf("%s",st);        top=0;        for(i=0;st[i];i++)        {            if(isalpha(st[i]))putchar(st[i]);            else            {                   if(st[i]==')')                   {                       while(top&&stack[top]!='(')putchar(stack[top--]);                       top--;                   }                   else                   {                       while(top&&stack[top]!='('&&cmp(stack[top],st[i]))putchar(stack[top--]);                       stack[++top]=st[i];                   }            }        }        while(top)putchar(stack[top--]);        puts("");    }    return 0;}


B题 Default Password

o(∩∩)o...哈哈,大水题,让所有人都能happy的过掉,但要比手速。。水题刷刷更健康~~~~

#include <iostream> using namespace std; int main(){    string st;    while(cin>>st)    {        if(st=="wujiawei")cout< <"hit";else cout <<"lose";        cout<<endl;    }    return 0;}


C题Censorship

额,对题意有些疑问,样例没看懂,感觉第三个样例答案应该是3有空再研究。。。

C题The Final Battle of Daydream

题意:给出1..n中的n-2个数,输出少了的两个数
比赛时内存给了1M,但是数据范围是300,000
挂在oj的题上显示给的内存是64M,应该是出问题了吧。。。


起初我就是开了个布尔数组,但是一直超内存,也就超一点点,眼看着别人一个个AC,心里那个滋味啊。。。。


后来看到最下面一行PS. because of the limit memory, iostream is not recommanded.
然后顿悟,去掉了#include<iostream>,然后就AC了


这么做绝对是水过,算一下内存:sizeof(bool)得到1,也就是1个字节,300,000B, 不知道hoj是否算的是字节,问下1+学长


正确的做法是根据给出的数列出两个方程组成方程组,解出答案


a+b=sum(n)-sum(left)
a^2+b^2=sum(n^2)-sum(left^2)


然后解出a和b
正解:

改编自OnePlus学长空间里的解题报告

#include <cstdio>#include <cstring>#include <cmath>#define sqr(x) ((x)*(x))#define PRINT(x) cout < <(#x)<<" "<<x<<endl;using namespace std;int main() {    double n;    while(scanf("%lf",&n)==1){        double N = 0.0, M = 0.0;        for(double i = 1; i <= n; i ++ ) {            N = N + i;            M = M + sqr(i);        }        N = ( 1 + n ) * n / 2;        M = ( n + 1 ) * ( n*2+1)*n/6;        for(int i = 2; i < n; i ++) {            double x; scanf( "%lf", &x );            N = N - x; M = M - sqr(x);        }        double delta = sqrt(2.0 * M - sqr(N));        //printf( "TEST %.10lf %.10lf %.10lf\n", N, M, delta);        double x = 0.5 * (N - delta), y = 0.5 * (N + delta);        printf( "%.0lf %.0lf\n", x, y );    }    return 0;}

水解:

#include <stdio .h>#include <string .h>#define N 300001bool f[N];int main(){    int n,i,a,tot;    while(scanf("%d",&n)==1)    {        memset(f,0,sizeof(f));        tot=0;        for(i=0;i<n -2;i++)        {            scanf("%d",&a);            f[a]=1;        }        for(i=1;i<=n;i++)            if(!f[i])            {                if(tot)putchar(' ');                tot++;                printf("%d",i);            }        puts("");    }    return 0;}


E题Costume Party

数学+搜索题

dfs找染色方案,每找出一种染色方案,使用的颜色总数为m1,则ans += A(m,m1)

#include <iostream>#define N 13using namespace std;int tot_edge,n,m,ans;int MOD=9999997;struct data{    int v;    data*next;}*adj[N],edge[N*N*2];int visit[N],visitcol[N];void push_edge(int u,int v){    edge[tot_edge].v=v;    edge[tot_edge].next=adj[u];    adj[u]=&edge[tot_edge++];}long long a(int n,int m){    long long ans=1;    while(m--)    {        ans=ans*n%MOD;        n--;    }    return ans;}void dfs(int k){    int i;    if(k==n)    {        int totcol=0;        for(i=1;i< =n;i++)            if(visitcol[i])totcol++;        if(totcol<=m)ans=(ans+a(m,totcol))%MOD;        return;    }    data *temp=adj[k];    bool color[N]={false};    while(temp)    {        if(visit[temp->v])            color[visit[temp->v]]=true;        temp=temp->next;    }    for(i=1;i< =n;i++)        if(!color[i]&&visitcol[i])        {            visit[k]=i;            dfs(k+1);        }    for(i=1;i<=n;i++)        if(!visitcol[i])break;    if(i<=n)    {        visit[k]=i;        visitcol[i]=1;        dfs(k+1);        visitcol[i]=0;    }    visit[k]=0;}int main(){    int k,a,b,i,cas=1;    while(scanf("%d %d %d",&m,&n,&k)==3)    {        tot_edge=0;        memset(adj,0,sizeof(adj));        for(i=0;i<k;i++)        {            scanf("%d %d",&a,&b);            a--;            b--;            push_edge(a,b);            push_edge(b,a);        }         memset(visit,0,sizeof(visit));        memset(visitcol,0,sizeof(visitcol));        ans=0;        dfs(0);        printf("Case #%d\n%d\n",cas++,ans);    }    return 0;}


F题Go Home

给了张图,每条边有个距离,还有个费用,求不超过此费用的最短路


我用spfa做的,保留了个二维的读列,但是比较慢,0.22s


看了OnePlus学长博客的<a href="http://www.oneplus.info/archives/230">解题报告</a>,给的做法是堆优化的dijkstra,我用xiaohao2跑了下,0.04s,挺快,直接用的algorithm里的堆(学习下)


OnePlus学长还给了个搜索做的,写的是宽搜,我提交后,时间好慢,0.28s,也许是因为用模板了。。。


看到wdk的只用了0.02s,orz。。。然后问他怎么做到的,他说直接搜索(深搜),看来我水了。。这道题水了。。。搜索竟然比正解快,搜索才是正解。。。。


然后我也写了个深搜,0.01s过掉,回头想了下先前写的spfa,也不过就是宽搜,但是宽搜怎么会比深搜慢那么多倍(都木有用到模板),改了很多次,bfs还是那么慢,纠结。。。。


有谁知道是怎么回事呀。。。


spfa(bfs)写法(变量名有点乱,囧。。。)
#include<stdio .h>#include<string .h>#define M 2010#define N 510#define NN 250010struct data{    int v,co,tm;    data*next;}*adj[N],edge[M];int q[NN],f[N][N],cost[NN],visit[N][N];int C,tot_edge,n;void push_edge(int u,int v,int c,int t){    edge[tot_edge].v=v;    edge[tot_edge].co=c;    edge[tot_edge].tm=t;    edge[tot_edge].next=adj[u];    adj[u]=&edge[tot_edge++];}void spfa(){    q[0]=1;    cost[0]=C;    f[1][C]=0;    int head=-1,tail=1,u,t,c;    data*tmp;    while((head+1)%NN!=tail)    {        head++;        head%=NN;        u=q[head];        c=cost[head];        t=f[u][c][/c];        tmp=adj[u];        visit[u][c][/c]=0;        while(tmp)        {            if(c>=tmp->co&&f[tmp->v][c language="-tmp->co"][/c]>t+tmp->tm)            {                f[tmp->v][c language="-tmp->co"][/c]=t+tmp->tm;                if(tmp->v!=n&&tmp->v!=1&&!visit[tmp->v][c language="-tmp->co"][/c])                {                    q[tail]=tmp->v;                    cost[tail]=c-tmp->co;                    visit[tmp->v][c language="-tmp->co"][/c]=1;                    tail++;                    tail%=NN;                }            }            tmp=tmp->next;        }    }}int main(){    int T,t,m,i,u,v,c,INF,ans;    scanf("%d",&T);    while(T--)    {        scanf("%d %d %d",&n,&m,&C);        tot_edge=0;        memset(adj,0,sizeof(adj));        for(i=0;i<m ;i++)        {            scanf("%d %d %d %d",&u,&v,&c,&t);            push_edge(u,v,c,t);            push_edge(v,u,c,t);        }        memset(visit,0,sizeof(visit));        memset(f,127,sizeof(f));        ans=INF=f[0][0];        spfa();        for(i=0;i<=C;i++)            if(f[n][i]<ans)ans=f[n][i];        if(ans==INF)puts("-1");        else printf("%d\n",ans);    }    return 0;}

dfs 写法:
#include<stdio .h>#include<string .h>#define N 510#define M 2010#define INF 1000000000int n,tot_edge,ans;bool visit[N];struct data{    int v,c,t;    data * next;    void update(int v,int c,int t,data *k)    {        this->v=v;        this->c=c;        this->t=t;        this->next=k;    }}edge[M],*adj[N];void push_edge(int u,int v,int c,int t){    edge[tot_edge].update(v,c,t,adj[u]);    adj[u]=&edge[tot_edge++];}void dfs(int k,int left,int tim){    if(tim>=ans)return;    if(k==n)ans=tim;    else    {        visit[k]=true;        data*temp=adj[k];        while(temp)        {            if(!visit[temp->v]&&left>=temp->c)                dfs(temp->v,left-temp->c,tim+temp->t);            temp=temp->next;        }        visit[k]=false;    }}int main(){    int t,i,a,b,c,m,C,T;    scanf("%d",&T);    while(T--)    {        scanf("%d %d %d",&n,&m,&C);        tot_edge=0;        memset(adj,0,sizeof(adj));        for(i=0;i<m ;i++)        {            scanf("%d %d %d %d",&a,&b,&c,&t);            push_edge(a,b,c,t);            push_edge(b,a,c,t);        }        ans=INF;        memset(visit,false,sizeof(visit));        dfs(1,C,0);        if(ans==INF)puts("-1");        else printf("%d\n",ans);    }}

dijkstra+堆优化:
#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>using namespace std;const int N = 505;const int INF = 0x3fffffff;int first[N];int cnt = 1;struct edge{    int u, v, c, t, next;} g[N * 4];void add(int u, int v, int c, int t){    g[cnt].u = u;    g[cnt].v = v;    g[cnt].c = c;    g[cnt].t = t;    g[cnt].next = first[u];    first[u] = cnt++;}struct node{    int w, u, t;    bool operator < ( const node &a ) const    {        return t > a.t;    }};int n, m, C;int dis[N][N];bool used[N][N];node queue[N * N];bool relax(int u, int w, int v, int c, int t){    if (dis[u][w] + t < dis[v][w + c])    {        dis[v][w + c] = dis[u][w] + t;        return true;    }    return false;}void dij(int u){    for (int i = 0; i <= n; ++i) for (int j = 0; j <= C; ++j) dis[i][j] = INF;    memset(used, false, sizeof(used));    int tail = 0;    int v, w, c, t;    dis[u][0] = 0;    queue[tail].u = u;    queue[tail].w = 0;    queue[tail].t = 0;    tail++;    make_heap(queue, queue + tail);    while (tail > 0)    {        pop_heap(queue, queue + tail);        tail--;        u = queue[tail].u;        if ( u == n ) break;        w = queue[tail].w;        if ( !used[u][w] )        {            used[u][w] = true;            for (int tmp = first[u]; tmp ; tmp = g[tmp].next)            {                v = g[tmp].v;                c = g[tmp].c;                t = g[tmp].t;                if ( w + c < = C && !used[v][w + c] && relax(u, w, v, c, t) )                {                    queue[tail].u = v;                    queue[tail].w = w + c;                    queue[tail].t = dis[v][w + c];                    tail++;                    push_heap(queue, queue + tail);                }            }        }    }    return;}int main(){    int cases, u, v, c, t;    scanf("%d", &cases);    while (cases--)    {        memset(first, 0, sizeof(first));        cnt = 1;        scanf("%d %d %d", &n, &m, &C);  // n:1~n        for (int i = 0; i < m; ++i)        {            scanf("%d %d %d %d", &u, &v, &c, &t);            add(u, v, c, t);            add(v, u, c, t);        }        dij(1);        int ans = INF;        for (int i = C; i >= 0; --i)        {            if (dis[n][i] != INF)            {                ans = min(ans, dis[n][i]);            }        }        printf("%d\n", ans == INF ? -1 : ans);    }    return 0;}


G题Alex's Problem

万恶的计算几何啊。。。鸭梨很大。。。
求截面面积。。。。坑爹啊。。。。更坑爹的是学长竟然做下来啦。。。


Alex 的problem很严重啊


没那份耐心去想,此题报告待写。。。

H题Zhou Yi II

水题,蛮好。。。
二进制转十进制。。。。
#include <iostream> using namespace std; int main(){    char st[100];    int n,i,ans;    while(scanf("%d",&n)==1)    {        getchar();        ans=0;        for(i=0;i<n ;i++)        {            gets(st);            ans<<=1;            if(strcmp(st,"---"))                ans++;        }        printf("%d\n",ans);    }    return 0;}

Okay,网络赛的报告就写到这,其中两道题待做,会尽快做掉。。。。
就这报告还写了这么长时间。。。。咳咳。。。不过很爽,很久都没安静做题了,这回泡在图书馆一下午+晚上,安安静静的做完这些事,挺好。。。。
原创粉丝点击