ACM Steps_Chapter Five_Section2

来源:互联网 发布:mac版pscc2018破解 编辑:程序博客网 时间:2024/06/05 06:53

统计难题

/*即每个结点有多个儿子结点。。。然后单词的前缀会在树中重合,而结点的数据域随题目而变,例如这题,数据域prefixNum表示含以该结点结尾的前缀的单词的个数。那么如果你想知道树中某单词是否存在,则数据域isWord == 1表示存在以该结点结尾的单词 字典树效率高在于他只需要遍历该单词*/#include <iostream>using namespace std;struct Node{    struct Node *child[26];    int perfixNum;//表示含以该结点结尾的前缀的单词的个数};Node *root;void Init()//初始化{    root = new Node;    for (int i = 0; i < 26; i++)    {        root->child[i] = NULL;    }}//插入void Insert(char word[]){    int len = strlen(word);    Node *pNode = root;    for (int i = 0; i < len; i++)    {        if (pNode->child[word[i] - 'a'] == NULL)        {            //不存在该结点,则创建一个            Node *newNode = new Node;            newNode->perfixNum = 1;            for (int j = 0; j < 26; j++)            {                newNode->child[j] = NULL;            }            pNode->child[word[i] - 'a'] = newNode;        }        else        {            pNode->child[word[i] - 'a']->perfixNum++;        }                pNode = pNode->child[word[i] - 'a'];    }}//查找,通过遍历该单词到该单词的结尾结点的prefixNum就是答案了int Find(char word[]){    int len = strlen(word);    Node *pNode = root;    int i;    for (i = 0; i < len; i++)    {        if (pNode->child[word[i] - 'a'] != NULL)        {            pNode = pNode->child[word[i] - 'a'];        }        else        {            break;        }    }    if (i == len)    {        return pNode->perfixNum;    }    else    {        return 0;    }}int main(){    char word[15], prefixWord[15];    Init();    while (gets(word), word[0] != 0)    {        Insert(word);    }    while (gets(prefixWord) != NULL)    {        printf("%d\n", Find(prefixWord));    }    return 0;}

Phone List

// Trie 基础模板#include <stdio.h>#include <string.h>#include <algorithm>#include <vector>#include <stack>#include <iostream>#define Max 100000#define sigma_size 10using namespace std;int ch[Max][sigma_size];bool val[Max];int cnt;char str[10002];int idx(char c){    return  c-'0';}bool insert(char *s){    int i,n=strlen(s);    int c,u=0;    for(i=0;i<n;i++)    {        c=idx(s[i]);        if(!ch[u][c])        {          memset(ch[cnt],0,sizeof(ch[cnt]));          val[cnt]=false;          ch[u][c]=cnt++;        }        if(val[u]) return false;        u=ch[u][c];    }    val[u]=true;    for(i=0;i<sigma_size;i++) //做题时开始忘记这、错了下    if(ch[u][i]) return false;    return true;}int main(){    int T;    int n,i;    scanf("%d",&T);    bool flag;    while(T--)    {        flag=true;        val[0]=0;        memset(ch[0],0,sizeof(ch[0]));        cnt=1;        scanf("%d",&n);        for(i=0;i<n;i++)        {            scanf("%s",str);            if(!insert(str))             flag=false;        }        if(flag)           printf("YES\n");        else           printf("NO\n");    }    return 0;}

Flying to the Mars

/*题目大意:给你一堆士兵的等级,等级高的的士兵可以当等级小的士兵的师傅,一个士兵最多一个师傅(可以没有),一个师傅最多1个徒弟(可以没有),如果是师徒关系,可以用一把扫帚练习技能,问你如果全部士兵都用过扫帚练习时最小需要的扫帚数量。解题思路:实质就是字典树的应用。如果所有士兵等级都不同,则就可以用一条师徒链,所以就需要一把扫帚,而如果出现2个相同等级的士兵,则需要开辟另外一条师徒链,以此类推,发现只要求出等级相同的最多士兵数,就需要多少把扫帚。*/#include<cstdio>#include<cstring>#include<algorithm>using namespace std;struct Trie{    int cnt;    Trie *child[10];    Trie(){cnt=0;memset(child,NULL,sizeof(child));}}*root;int ans;void insert(char *s){    int id;    Trie *p=root;    for(int i=0;s[i];)    {        id=s[i]-'0';        if(!p->child[id])           p->child[id]=new Trie();        p=p->child[id];        ++i;    }    p->cnt++;    ans=max(ans,p->cnt);}int main(){    char s[35];    int n,pos;    for(;~scanf("%d",&n);)    {        ans=0;        root=new Trie();        for(int i=0;i<n;++i)        {            scanf("%s",s);            pos=0;            for(;s[pos]=='0';++pos);            insert(s+pos);        }        printf("%d\n",ans);    }    return 0;}

魔咒词典

#include<cstdio>#include<algorithm>using namespace std;char str[130];//数据读入所用 char moz[101000][30];//魔咒 char func[101000][90];//对应功能 char Result[130];//结果 int val[101000];//对魔咒排序所用int vafun[101000];//对功能排序所用 int tot=0;//魔咒总个数 bool cmp(int a,int b){//快排魔咒(从小到大,可也以从大到小,看自己喜欢)if(strcmp(moz[a],moz[b])==-1) return true;return false;}//可以直接写成return strcmp(moz[a],moz[b])==-1;bool _cmp(int a,int b){//对功能排序 if(strcmp(func[a],func[b])==-1) return true;return false;}//return strcmp(func[a],func[b])==-1;bool Finda(char *s){//二分查找魔咒 int left=0,right=tot-1,mid;while(left<=right){mid=(left+right)>>1;//mid=(left+right)/2; if(!strcmp(moz[val[mid]],s)){strcpy(Result,func[val[mid]]);//把功能复制给结果Result return true;//返回 }else if(strcmp(moz[val[mid]],s)==1){right=mid-1;}else left=mid+1;}return false;}bool Findb(char *s){//十分查找功能 int left=0,right=tot-1,mid;while(left<=right){mid=(left+right)>>1;if(!strcmp(func[vafun[mid]],s)){strcpy(Result,moz[vafun[mid]]+1);int len=strlen(moz[vafun[mid]]);Result[len-2]='\0';return true;}else if(strcmp(func[vafun[mid]],s)==1){right=mid-1;}else left=mid+1;}return false;}int main(){int i,Q,len;bool flag;while(gets(str),str[0]!='@'){len=strlen(str);for(i=0;str[i];i++){//存入魔咒 moz[tot][i]=str[i];if(str[i]==']') break;}moz[tot][++i]='\0';val[tot]=tot;strcpy(func[tot],str+i+1);//存入功能 func[tot][len-i-1]='\0';vafun[tot]=tot++;}sort(val,val+tot,cmp);sort(vafun,vafun+tot,_cmp);scanf("%d",&Q);getchar();while(Q--){gets(str);if(str[0]=='['){flag=Finda(str);if(flag==false) puts("what?");else puts(Result);}else{flag=Findb(str);if(flag==false) puts("what?");else puts(Result);}memset(Result,0,sizeof(Result));}return 0;}

确定比赛名次

/*简单拓扑排序问题,问题在于选取入度为零的点。*/#include <stdio.h>#define MAX 505#include <string.h> int map[MAX][MAX], N, M, hash[MAX]; void update( int x ){    for( int i= 1; i<= N; ++i )    {        map[x][i]= 0;    } } void Tsort(  ){    for( int i= 1; i<= N; ++i )    {        for( int j= 1; j<= N; ++j )        {            if( hash[j] )            {                continue;            }            int sign= 1;            for( int k= 1; k<= N&& sign; ++k )            {                if( map[k][j] )                {                    sign= 0;                    break;                }            }            if( sign )            {                printf( i== 1? "%d": " %d", j );                hash[j]= 1;                update( j );                break;            }        }    }    puts( "" );} int main(  ){    while( scanf( "%d%d", &N, &M )!= EOF )    {        memset( map, 0, sizeof( map ) );        memset( hash, 0, sizeof( hash ) );        for( int i= 1; i<= M; ++i )        {            int x, y;            scanf( "%d%d", &x, &y );            map[x][y]= 1;        }        Tsort(  );    }    return 0;}

产生冠军

#include <stdio.h>#include <string.h>#define MAXN 1005int n, top_name, indegree[MAXN];char name[MAXN][15];void Init(){    top_name = 0;    memset(indegree, 0, sizeof(indegree));}int find_str(char *s){    int i;    for(i=0; i<top_name; i++){        if(strcmp(name[i], s) == 0) break;    }    if(i==top_name){        strcpy(name[top_name++], s);    }    return i;}int main(){    int i, k, cnt, pos1, pos2;    char s1[15], s2[15];    while(scanf("%d", &n) == 1 && n){        Init();        for(i=0; i<n; i++){            scanf("%s %s", s1, s2);            pos1 = find_str(s1), pos2 = find_str(s2);            indegree[pos2]++;        }        cnt = 0;        for(i=0; i<top_name; i++){            if(indegree[i] == 0){k = i; cnt++;}            if(cnt > 1) break;        }        if(cnt == 1) printf("Yes\n");        else printf("No\n");    }    return 0;}

Box Relations

/*把一个箱子分成三个面,即X,Y,Z拿X来说,把这个面分为上下两部分,上面记为1,下面记为1+n,当读入X A B条件的时候,那么A箱的下表面和B箱的上表面构成关系,虽然题目中说是A要比B小,但是由于我们最后记录的时候i是从小到大来的,所以我们把A放在B的上面,结果是A的坐标比B小 当读入I A B的时候,那么A箱的上表面大于B箱的下表面,B箱的上表面要大于A箱的下表面,在纸上画个图就很好理解了,接下来就是分成X,Y,Z三个面分别拓扑就好*/ #include <cstdio> #include <cstring> using namespace std;  const int N=2010; bool g[3][N][N]; int ind[3][N],n; int topo[3][N]; int x[N],y[N],z[N]; bool toposort(int k) {     memset(ind[k],0,sizeof(ind[k]));     for(int v=1;v<=n;v++)         for(int u=1;u<=n;u++)             if(g[k][u][v]) ind[k][v]++;     for(int i=0;i<n;i++)     {         int u;         for(u=1;u<=n;u++)             if(ind[k][u]==0) break;         if(u>n) return false;         topo[k][i]=u; ind[k][u]--;         for(int v=1;v<=n;v++)             if(g[k][u][v]) ind[k][v]--;     }     return true; } int main() {     int m,C=0;     while(scanf("%d%d",&n,&m),n||m)     {         memset(g,0,sizeof(g));         for(int i=0;i<3;i++)             for(int u=1;u<=n;u++) g[i][u][u+n]=1;         while(m--)         {             char op[2];             int u,v;             scanf("%s%d%d",op,&u,&v);             if(op[0]=='I')             {                 for(int i=0;i<3;i++)                     g[i][v][u+n]=g[i][u][v+n]=1;             }             else             {                 int k=op[0]-'X';                 g[k][u+n][v]=1;             }         }         n*=2;         bool flag=true;         for(int i=0;flag&&i<3;i++)             if(!toposort(i)) flag=false;         n/=2;         if(flag)         {             printf("Case %d: POSSIBLE\n",++C);             for(int i=0;i<2*n;i++)                 x[topo[0][i]]=y[topo[1][i]]=z[topo[2][i]]=i;             for(int i=1;i<=n;i++)                 printf("%d %d %d %d %d %d\n",x[i],y[i],z[i],x[i+n],y[i+n],z[i+n]);         }         else printf("Case %d: IMPOSSIBLE\n",++C);         printf("\n");     }     return 0; }

Entropy

#include <iostream>#include <cstdlib>#include <cstdio>#include <queue>using namespace std;const int MAXN = 1010;struct node{    int data;    int dep;    node *L, *R;    node()    {        data = 0;        dep = 0;        L = NULL;        R = NULL;    }    bool operator <(node a) const    {        return a.data < data;    } //重载小于号 };int ans;char str[MAXN];int huf[MAXN];priority_queue<node> Q;void BuildHuffman(){    node *p, *q, *T;    while(Q.size() != 1)    {        p = new node();        q = new node();        T = new node();        *p = Q.top(); Q.pop();        *q = Q.top(); Q.pop();        T->data = p->data + q->data;        T->L = p, T->R = q;        Q.push(*T);    }    return ;}queue<node> q;void solve(){    node root;    root = Q.top(); Q.pop();    root.dep = 0;    q.push(root);    while(!q.empty())    {        node x = q.front(); q.pop();        if(x.L)        {            x.L->dep = x.dep + 1;            q.push(*(x.L));        }        if(x.R)        {            x.R->dep = x.dep + 1;            q.push(*(x.R));        }        if(!x.L && !x.R)        {            ans += x.dep * x.data;        }    }}/*void dfs(node *p, int dep){    if(!p->L && !p->R)    {        ans += p->data * dep;    }    if(p->L)    {        dfs(p->L, dep+1);    }    if(p->R)    {        dfs(p->R, dep+1);    }}*/void init(){    ans = 0;    while(!Q.empty()) Q.pop();    while(!q.empty()) q.pop();    memset(huf, 0, sizeof(huf));}int main(){    while(scanf("%s", str) && strcmp(str, "END"))    {        init();        int len = strlen(str);        for(int i = 0; str[i]; i++)        {            huf[str[i]]++;        }        for(int i = 0; i < 100; i++) if(huf[i])        {            node t;            t.data = huf[i];            Q.push(t);        }        if(Q.size() == 1) //特判        {            printf("%d %d 8.0\n", len*8, len);            continue;        }        BuildHuffman();        solve();        //dfs(root, 0); 用DFS也可以实现         printf("%d %d %.1lf\n", len*8, ans, len*8.0/ans);    }    return 0;}


原创粉丝点击