程序设计实训

1、ASCII


#include<stdio.h>int main(){
    char ch;
    int a=0,b=0;
    while((ch=getchar())!=EOF)
    {        
        if(b==0)
        {
            printf("%05X",a);                        
            printf(" %02X",ch);
        }    
        if(b!=0&&b<16)
        {
            printf(" %02X",ch);                
        }b++;        
        if(b==16)
        {
            b=0;
            a++;
            printf("\n");
        }
        
    }    }

2、染色

#include<stdio.h>int a[105],b[105];int main(){
    int t,m,n,k;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d%d",&m,&n,&k);
        int x,y;
        int visa=0,visb=0;
        for(int i=0;i<105;i++)
        {
            a[i]=0;
            b[i]=0;
        }
        while(k--)
        {
            scanf("%d%d",&x,&y);
            if(a[x]==0)
            {
                a[x]=1;
                visa++;
            }
            if(b[y]==0)
            {
                b[y]=1;
                visb++;
            }
        }
        printf("%d\n",m*n-visa*visb);
    }
return 0;}

3、Bob’s Password

#include<stdio.h>#include<string.h>#include<stdlib.h>#include <iostream>using namespace std;int main(){
    int t;
    scanf("%d",&t);
    int a[9][9]={0,1,0,1,1,1,0,1,0,
                     1,0,1,1,1,1,1,0,1,
                     0,1,0,1,1,1,0,1,0,
                     1,1,1,0,1,0,1,1,1,
                     1,1,1,1,0,1,1,1,1,
                     1,1,1,0,1,0,1,1,1,
                     0,1,0,1,1,1,0,1,0,
                     1,0,1,1,1,1,1,0,1,
                     0,1,0,1,1,1,0,1,0};
    int b[100];
    while(t--){
        string s;
        cin>>s;
        int flag = 1;
        int len = s.length();
        memset(b,0,sizeof(b));
        for(int i = 0;i < len-1;i++){
            if(a[s[i]-'1'][s[i+1]-'1']==1){
                b[s[i]-'1'] = 1;
            }
            else{
                if(b[(s[i]+s[i+1]-2*'1')/2]==1)
                {
                    b[s[i]-'1'] = 1;
                }
                else
                {
                    flag = -1;
                    break;
                }
            }
        }
        if(flag==1)
           puts("Yes");
        else
            puts("No");
}}

4、Alice and Bob
输入
第一行输入一个整数K,表示游戏的次数。 以后每两行表示一个样例,第一行是Alice骰子的点数。第二行是Bob骰子的点数。
输出
如果是Alice赢,输出"Alice",如果是Bob赢,输出"Bob",否则输出"Draw"。

#include <stdio.h>
int main()
{
    int ct;
    scanf("%d",&ct);
    while(ct--)
    {
        int a,b,c,k=2,A=0,B=0,cot=0;
        while(k--){
            scanf("%d %d %d",&a,&b,&c);
            int ai=a,bi=b,ci=c;
            if(a==1) a=16;
            if(b==1) b=16;
            if(c==1) c=16;
            if(a==b&&b==c)
            {    
                cot=a*1000;
            }
            else if(a==b)
            {
                cot=a*100+c;
            }
            else if(a==c)
            {
                cot=a*100+b;
            }
            else if(b==c)
            {
                cot=b*100+a;
            }
            else
            {    
                cot=ai+bi+ci;
            }
            if(k==1)
                A=cot;
            else
                B=cot;
        }
        if(A>B)
            printf("Alice\n");
        else if(A<B)
            printf("Bob\n");
        else
            printf("Draw\n");
    }
    return 0;
}

5、矩阵转置就是把原矩阵A的所有元素aij转成矩阵B的bji。 现实中,大部分的矩阵都是稀疏的,所以,存储矩阵时,我们可以只存储存储每个非零元素的座标和值,并且按行优先排序。

#include <stdio.h>
int a[10001], b[10001], c[10001];
int va[10001], vb[10001], vc[10001];
int main() 
{
  int t;
  scanf("%d", &t);
  while (t--) 
  {
    int n, m, k,i,j;
    scanf("%d%d%d", &n, &m, &k);
    for (i = 0; i < k; ++i) 
       scanf("%d%d%d", &a[i], &b[i], &c[i]);
    int t = 0;
    for (i = 0; i < m; ++i) {
      for (j = 0; j < k; ++j) {
        if (b[j] == i) {
          va[t] = b[j];
          vb[t] = a[j];
          vc[t] = c[j];
          t++;
        }
      }
    }
    for (i = 0; i < k; ++i) {
      printf("%d %d %d\n", va[i], vb[i], vc[i]);
    }
    printf("\n");
  }
}

6、Alice和Bob在玩骰子游戏,他们用三颗六面的骰子,游戏规则如下:

点数的优先级是1点最大,其次是6,5,4,3,2。
三个骰子点数相同,称为"豹子",豹子之间按点数优先级比较大小。
如果只有两个骰子点数相同,称为"对子",对子之间按点数优先级比较大小。
其他情况称为"点子",点子按点数和比较大小。
豹子比对子、点子大,对子比点子大,如果对子的点数优先级相同,就看剩余那个骰子的点数优先级。

#include <stdio.h>
int main()
{
    int count,a,b,c,ai,bi,ci,A,B,k,sum;
    scanf("%d",&count);
    while(count--)
    {
        
        k=2;A=0;B=0;sum=0;
        while(k--){
            scanf("%d %d %d",&a,&b,&c);
            int ai=a,bi=b,ci=c;
            if(a==1) a=16;
            if(b==1) b=16;
            if(c==1) c=16;
            if(a==b&&b==c)
            {    
                sum=a*1000;
            }
            else if(a==b)
            {
                sum=a*100+c;
            }
            else if(a==c)
            {
                sum=a*100+b;
            }
            else if(b==c)
            {
                sum=b*100+a;
            }
            else
            {    
                sum=ai+bi+ci;
            }
            if(k==1)
                A=sum;
            else
                B=sum;
        }
        if(A>B)
            printf("Alice\n");
        else if(A<B)
            printf("Bob\n");
        else
            printf("Draw\n");
    }
    return 0;
}

Robot
题目描述
有N个任务需要Robot去完成,这个N个任务的地点在一个数轴上,座标为1到n。每个任务需要先完成ai个任务才能开始去做。Robot可以在直线上左右移动,初始位置位于任务1的地点,方向朝向数轴正方向。请问Robot最少转换多少次方向可以完成所有的任务。
输入
存在多个样例。
每个样例的第一行是一个整数n(1≤n≤1000),
第二行是一个n个整数a1,a2,⋯,an(0≤ai<n)。
输入数据保证一定能完成任务。
输出
每行输出一个样例的结果
样例输入
3
0 2 0
7
0 3 1 0 5 2 6
样例输出
1
2

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<memory.h>
int main()
{
    int n;
    int a[1001],s[1001];
    while(scanf("%d",&n)!=EOF)
    {
        int i,t=0,f=0;
        memset(s,0,sizeof(s));
        for(i=0;i<n; i++) 
           scanf("%d",&a[i]);
        while(f!=n)
        {
            for(i=0; i<n; i++)
            {
                if((f>=a[i])&&!s[i])
                {
                    f++;
                    s[i]=1;
                }
            }
            if(f==n) break;
               t++; 
            for(i=n-1; i>=0; i--)
            {
                if((f>=a[i])&&!s[i])
                {
                    f++;
                    s[i]=1;
                }
            }
            if(f==n) 
               break;
            t++;
        }
        printf("%d\n",t);
}

6、Matrix Word
题目描述
一个n×m的矩阵,矩阵每个元素是一个小写英文字母,如果某个字母所在行或者列不是唯一的,那么我们就删掉这个字符。最后,我们按矩阵的从上到下,从左到右,可以得到一个单词。

#include<stdio.h> char x[101][101];int n, m;int s(int i, int j,char c);int main(){
    int i,j;
    while((scanf("%d %d ", &n, &m))!=EOF)
    {
        for(i = 0;i<n;i++)
        {
            for(j=0;j<m;j++)
            {
                x[i][j]=getchar();
            }
            getchar();
        }
        for(i = 0; i < n; i++)
        {
            for(j = 0; j < m; j++)
            {
                if(!s(i, j, x[i][j])) 
                   putchar(x[i][j]);
            }
        }
        printf("\n");
    }}int s(int i, int j,char c)//判断一个字母所在的行和列是否唯一 {
    int k;
    for(k = 0; k < m; k++)
        if(x[i][k] == c && k != j) 
          return 1;
    for(k = 0; k < n; k++)
        if(x[k][j] == c && k != i) 
          return 1;
return 0;}

7、题目描述
给你n个数,祛除其中的重复的数,并保持第一次出现的数原有的相对顺序。比如{3,2,2,3,1},那么祛除重复元素以后为{3,2,1}。
输入
第一行是一个整数K,K表示样例的个数,不超过100。
每个样例的第一行是一个整数n(1≤n≤10000。) 表示数的个数;第二行是n个正整数,其值不超过109。
输出
每行输出一个样例的结果,每个整数之间用一个空格隔开。

样例输入
2
5
3 2 2 3 1
3
1 2 3
样例输出
3 2 1
1 2 3

#include <stdio.h>
int a[10000];
main(){
    int n,i,b,t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(i=0;i<n;i++)
            scanf("%d",&a[i]);
        for(b=0;b<n-1;b++)
        {
            if(a[b]==-1)continue;
            for(i=b+1;i<n;i++)
            {
                if(a[b]==a[i])
                    a[i]=-1;
            }
        }
        int c=0,d[10000];
        for(i=0;i<n;i++)
        {
            if(a[i]!=-1)
            {
                d[c]=a[i];
                c++;
            }
        }
        for(i=0;i<c-1;i++)
            printf("%d ",d[i]);
        printf("%d\n",d[c-1]);   
}
}

七、Colombian Number
题目描述
对于正整数n,不存在整数k,使得n等于k加上k的数码累加和,我们称这样的数是哥伦比亚数或者自我数。
比如 11就不是一个哥伦比亚数,因为10加上10的数码累加和1等于11;而20则是一个哥伦比亚数。

#include<stdio.h> int k,t,n,i;int self_num(int a){
    int c=0;
    while(a!=0)
    {
        c+=a%10;a/=10;
    }
    return c;}//求m数码之和int main(){
    scanf("%d",&k);
    while(k--)
    {
        int flag=0;
        scanf("%d",&n);
        for(i=n-1;i>n-81&&i>0;i--)
        {
            if(self_num(i)+i==n)
                flag=1;
        }
        if(flag)  
            printf("No\n");
        else 
           printf("Yes\n");
    }
return 0;}

1246
Matrix Transposition
题目描述
矩阵转置就是把原矩阵A的所有元素aij转成矩阵B的bji。 现实中,大部分的矩阵都是稀疏的,所以,存储矩阵时,我们可以只存储存储每个非零元素的座标和值,并且按行优先排序。
输入
第一行是一个整数T,(0<T≤10),表示样例的数目。
每个样例的第一行是三个整数N,M,K,1≤N,M≤1000,1≤K≤10000,分别表示矩阵的行数,列数,非零元素个数。
以后的K行,每行三个整数X,Y,V,0≤X<N,0≤Y<M,−100≤V≤100,表示元素的行,列,值。
数据保证输入元素的顺序按行优先有序。
输出
输出每个样例的结果,每个样例输出之后有一个空行。

#include <stdio.h>
int a[10001], b[10001], c[10001];
int va[10001], vb[10001], vc[10001];
int main() 
{
  int t;
  scanf("%d", &t);
  while (t--) 
  {
    int n, m, k,i,j;
    scanf("%d%d%d", &n, &m, &k);
    for (i = 0; i < k; ++i) 
       scanf("%d%d%d", &a[i], &b[i], &c[i]);
    int t = 0;
    for (i = 0; i < m; ++i) {
      for (j = 0; j < k; ++j) {
        if (b[j] == i) {
          va[t] = b[j];
          vb[t] = a[j];
          vc[t] = c[j];
          t++;
        }
      }
    }
    for (i = 0; i < k; ++i) {
      printf("%d %d %d\n", va[i], vb[i], vc[i]);
    }
    printf("\n");
  }
}

1262

#include <bits/stdc++.h>using namespace std;struct node {
  int a, b, a1, k;
  //从大到小排列
  friend bool operator<(node X, node Y) { return X.a < Y.a; }};
priority_queue<node> pq;// max{0,ai−k×bi}int main() {
  int T, n, m, a, b;
  scanf("%d", &T);
  while (T--) {
    while (!pq.empty()) pq.pop();  //每次先将队列清空
    scanf("%d%d", &n, &m);
    node nd;
    while (n--) {
      scanf("%d%d", &a, &b);
      nd.a = a;
      nd.a1 = a;
      nd.b = b;
      nd.k = 0;
      pq.push(nd);
    }
    int cnt = 0;
    while (!pq.empty()) {
      nd = pq.top();
      pq.pop();
      if (nd.b != 0) {
        cnt += nd.a;
        nd.k++;
        nd.a = max(0, nd.a1 - nd.k * nd.b);  //更新
        m--;
        pq.push(nd);
      } else {
        cnt += nd.a * m;  //此时数目是当前最多并且不需要更新
        m = 0;
        break;
      }
      if (!m) break;
    }
    printf("%d\n", cnt);
  }
 // system("pause");
  return 0;}

1277
样例输入
A
B
C
样例输出
A
A A
A
ABA
A A
ABA ABA
A
ABA
ABCBA
A A
ABA ABA
ABCBA ABCBA

#include <cstdio>int main() {
  char ch;
  while (scanf("%c", &ch) != EOF) {
    int row, col, col1, space;  //行数列数和空格数
    row = ch - 'A' + 1;
    space = 2 * row - 1;
    col = space + 1;
    col1 = row + space;
    //上三角
    for (int i = 0; i < row; ++i) {
      for (int k = i; k < space; ++k) putchar(' ');
      char ch1 = ' ';
      for (int j = 0; j < col - space + i; ++j) {
        putchar('A' + j);
        ch1 = 'A' + j;
      }
      for (int l = 0; l <= col1 - col - row + i; ++l) {
        putchar(ch1 - l - 1);
      }
      putchar('\n');
    }
    //左右三角
    int space1 = space - row, space2 = space, len = 2 * row - 1;
    col = space1 + 1;
    for (int i = 0; i < row; ++i) {
      //左
      for (int k = i; k < space1; ++k) putchar(' ');
      char ch1 = ' ';
      for (int j = 0; j < col - space1 + i; ++j) {
        putchar('A' + j);
        ch1 = 'A' + j;
      }
      int num = 0;
      for (int l = 0; l <= len - col - row + i; ++l) {
        putchar(ch1 - l - 1);
        num++;
      }
      //  右
      int col2 = space + 1;
      for (int k = 0; k < space2 - 2 * num; ++k) putchar(' ');
      ch1 = ' ';
      for (int j = 0; j < col2 - space2 + i; ++j) {
        putchar('A' + j);
        ch1 = 'A' + j;
      }
      for (int l = 0; l < col2 - col - row + i; ++l) {
        putchar(ch1 - l - 1);
      }
      putchar('\n');
    }
  }
 // system("pause");}

1280
String Hash
题目描述
把字符串进行Hash,来判断字符串是否相等是一种很常见的技术。 对一个只含英文小写字母字符串进行Hash,一种比较简单的方法是把字符串看成一个26进制的数,az分别表示025,获得这个值后对某个素数p取模。但是因为a是0,所以"abc"和"bc"的Hash值肯定是一样的,为了解决这个问题,我们假定在字符串前加入字符b(即26进制数最高位为1)比如p=11,字符串"abc",相当于26进制数"1012",所以对应的十进制数为17604,所以哈希值为4。
我们假定p=1000000007,请将给定的字符串给出对应的hash值。

输入
存在多个样例。每行一个只含英文小写字母的字符串,长度不超过1000个字符。

输出
每行输出一个样例的结果

样例输入
abc
bc
abcdefghijklmnopqrstuvwxyz
样例输出
17604
704
115471061

#include<stdio.h>
#include<math.h>
#include<string.h>
int main()
{   int j;
    int c[1001];
    c[0]=1;
    for(j=1;j<1001;j++)
    {
        c[j]=(c[j-1]*26)%1000000007;
    }
    char a[10010];
    int  n[10010];
    while(scanf("%s",&a)!=EOF){
        getchar();
        int i;
        n[0]=1;
        for(i=0;i<strlen(a);i++)
        {
            n[i+1]=a[i]-'a';
        }
        int s=0;
        for(i=0;i<(int)strlen(a)+1;i++)
        {
           int  q=strlen(a)-i;
           int  p=c[q];
           s=s+(n[i]*p)%1000000007;
           s=  s%1000000007;
        }

        printf("%d\n",s);
    }
} 

1281
Cute String
题目描述
Alice的记忆力不太好,如果一个句子中含的单词(每个单词之间用一个空格隔开)数量超过10,或者句子中字母种类(不区分大小写)超过10个,她就会记不住。现在给你若干个句子,请写个程序判断一下Alice是否能记住这些句子。
样例输入
Alice is a smart girl
but she is bad in memory
a b c d e f g h i j
A B C D E F G H I J K
样例输出
Yes
No
Yes
No

#include <bits/stdc++.h>using namespace std;int main() {
  string s;
  set<char> se;
  while (getline(cin, s)) {
    se.clear();
    int cnt = 0;
    for (int i = 0; i < s.length(); ++i) {
      if (s[i] == ' ') cnt++;
    }
    if (cnt > 9) {
      cout << "No" << endl;  //单词数量超过10记不住
    } else {                 //单词数量没超过10
      char ch[201];
      int num = 0;
      strcpy(ch, s.c_str());
      for (int i = 0; i < s.length(); ++i) {
        if (ch[i] != ' ') ch[i] = toupper(ch[i]);
      }
      for (int i = 0; i < s.length(); ++i) {
        if (ch[i] != ' ') se.insert(ch[i]);
      }
      cout << ((se.size() > 10) ? "No" : "Yes") << endl;
    }
  }
  // system("pause");}

1284
多项式
题目描述

f(x)=∑i=0nai×ximodm

输入
第一行是一个整数T(1≤T≤1000),表示样例的个数。
每个样例的第一行是三个整数n(1≤n≤10),m(1≤m≤10000),x(1≤x≤10000)。
第二行是n+1个整数{ai∣i=n,n−1,⋯,0,0≤ai≤10000}。

输出
每行输出一个非负整数,即一个样例的结果。

样例输入
2
1 10 2
2 1
1 10 2
1 2
样例输出
5
4
样例解释
第一个样例,表达式为f(x)=2x+1mod10,所以f(2)=5 。
第二个样例,表达式为f(x)=x+2mod10,所以f(2)=4。

#include<stdio.h>
#define  ll __int64
int n,m,x;
int a[100];
ll qpow(ll a,ll n)//记得每次要对值取模
{
    ll r=1;
    while(n)
    {
        if(n&1)
            r=r*a%m;
        a=a*a%m;
        n>>=1;
    }
    return r;
}
int main()
{
    int T,i;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d%d",&n,&m,&x);
        ll sum = 0;
        for(i=n;i>=0;i--)
        {
            scanf("%d",a+i);
            sum = (sum + (ll)a[i]*(ll)qpow(x,i))%m;
        }
        printf("%d\n",sum);
    }
    return 0;
}

1286
比赛
[ Submit Code ] [ Top 20 Runs ] [ Runs Status ]
Acceteped : 385 Submit : 914
Time Limit : 1000 MS Memory Limit : 65536 KB

Description
Contest
题目描述
有n名选手参加比赛,从1∼n编号。每场比赛由两位选手对决,失败的被淘汰。为了增加比赛的观赏性,举办方并不想比赛双方实力相差太大的,所以决定,每场比赛的两位选手,之前胜场次数之差不能超过1。同时,鸡贼的举办方又不想冠军选手比赛太少了(严重影响比赛收入),希望冠军选手比赛场次越多越好。作为选手的你,当然不希望夺冠路上比赛场次太多,请问在这个赛制下,冠军最多比赛多少场?

输入
存在不超过10000组样例。每行一个整数n(1≤n≤1018)。

输出
每行输出一个样例的结果,为一个整数。

样例输入
1
2
3
10
1000000000000000000
样例输出
0
1
2
4
85
样例解释
我们假定冠军是1号。
第3个样例,1号依次击败2和3号。
第4个样例,其中一种比赛路线是1击败2,3击败4,1击败3,5击败6,1击败5,7击败8,9击败10,7击败9,1击败7。

#include <bits/stdc++.h>using namespace std;typedef long long ll;
ll dp[10000], n;void init() {
  memset(dp, 0, sizeof(dp));
  dp[0] = 1, dp[1] = 2;
  for (int i = 2; i < 10000; ++i) dp[i] = dp[i - 1] + dp[i - 2] + 1;}int main() {
  init();
  while (~scanf("%I64d", &n)) {
    for (int i = 0; i < 10000; ++i) {
      if (n <= dp[i]) {
        printf("%d\n", i);
        break;
      }
    }
  }
  // system("pause");

1272

#include <bits/stdc++.h>using namespace std;int main() {
  string s;
  while (cin >> s) {
    int u = 0, d = 0, l = 0, r = 0;
    for (int i = 0; i < s.length(); ++i) {
      if (s[i] == 'U')
        u++;
      else if (s[i] == 'D')
        d++;
      else if (s[i] == 'L')
        l++;
      else if (s[i] == 'R')
        r++;
    }
    if (l == r + u && !d || l == r + d && !u || r == l + u && !d ||
        r == l + d && !u || d == u + l && !r || d == u + r && !l ||
        u == d + l && !r || u == d + r && !l)
      printf("Yes\n");
    else
      printf("No\n");
  }}

矩阵的鞍点

#include<stdio.h>
#include<string.h>
int a[101][101];
int h[101][2],l[101][2];
int max(int i,int j)
{
    if(i<j)
      return j;
    else
      return i;
}
int min(int i,int j)
{
    if(i>j)
      return j;
    else
      return i;
}
int n,m;
int main()
{
    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        int i,j;
        for(i=0;i<101;i++)
          for(j=0;j<2;j++)
          {
              h[i][j]=-1;
              l[i][j]=-1;
          }             
        for(i=0;i<n;i++)
        for(j=0;j<m;j++)
        {
            scanf("%d",&a[i][j]);
            if(h[i][0]<0)    h[i][0]=a[i][j];
            else             h[i][0]=max(h[i][0],a[i][j]);
            if(h[i][1]<0)    h[i][1]=a[i][j];
            else             h[i][1]=min(h[i][1],a[i][j]);
            if(l[j][0]<0)    l[j][0]=a[i][j];
            else             l[j][0]=max(l[j][0],a[i][j]);
            if(l[j][1]<0)    l[j][1]=a[i][j];
            else             l[j][1]=min(l[j][1],a[i][j]);
        }
        int ans=0;
        for(i=0;i<n;i++)
        for(j=0;j<m;j++){
            if(a[i][j]==h[i][0]&&a[i][j]==l[j][1])
                ans++;
            else if(a[i][j]==h[i][1]&&a[i][j]==l[j][0])
                ans++;
        }
        if(ans)printf("%d\n",ans);
        else{printf("None\n");continue;}
        for(i=0;i<n;i++)
        for(j=0;j<m;j++){
            if(a[i][j]==h[i][0]&&a[i][j]==l[j][1])
                printf("%d %d %d\n",i,j,a[i][j]);
            else if(a[i][j]==h[i][1]&&a[i][j]==l[j][0])
                printf("%d %d %d\n",i,j,a[i][j]);
        }
    }
    return 0;
}
#include <stdio.h>
#include <stdlib.h>
typedef struct HNode *Heap;  //堆的类型定义
typedef int Elementype[2];
struct HNode 
{
    Elementype *Data; //存储元素的数组  //堆是完全二叉树,用数组存储利用率高
    
    int size; //堆中当前元素的个数
    int capacity; //堆的最大容量
};
typedef Heap MaxHeap; //最大堆
typedef Heap MinHeap; //最小堆
#define MAXDATA 1000  //该值应根据情况定义为大于堆中所有可能元素的值
MaxHeap CreateHeap(int MaxSize)
{
    //创建容量为MaxSize的空的最大堆
    MaxHeap H = (MaxHeap)malloc(sizeof(struct HNode));
    H->Data = (Elementype*)malloc((MaxSize+1)*sizeof(Elementype));
    H->size = 0;
    H->capacity = MaxSize;
    H->Data[0][0] = MAXDATA; //定义“哨兵”为大于堆中所有可能元素的值
    return H;
}
int IsFull(MaxHeap H)
{
    return H->size == H->capacity;
}
//bool
int Insert(MaxHeap H, Elementype x)
{
    //将元素x插入最大堆H,其中H->Data[0]已经定义为哨兵
    int i;
    if (IsFull(H))
    {
        printf("最大堆已满!");
        return 0;
    }
    i = ++H->size; //i指向插入后堆中的最后一个元素的位置
    //先直接到插入到数组最后的元素,然后在调整堆    
    for (; H->Data[i / 2][0] < x[0];i/=2)  //父节点比它小
    {
        H->Data[i][0] = H->Data[i/2][0]; // 和父节点交换
        H->Data[i][1] = H->Data[i/2][1];
    }
    H->Data[i][0] = x[0]; //找到插入位置,插入
    H->Data[i][1] = x[1];
    return 1;
}
/*------------建造最大堆----------------------*/
void PrecDown(MaxHeap H, int p)
{
    //下滤:将H中以H->Data[p]为根的子堆调整为最大堆
    int Parent, Child;
    Elementype x;
    x[0] = H->Data[p][0]; //取出根节点存放的值
     x[1] = H->Data[p][1];
    for (Parent = p; Parent * 2 <= H->size;Parent=Child)
    {
        Child = Parent * 2;
        if ((Child!=H->size)&&(H->Data[Child][0]<H->Data[Child+1][0]))
        {
            Child++; //Child指向左右子节点的较大者
        }
        if (x[0]>=H->Data[Child][0])
        {
            break;
        }
        else   /* 下滤X */
        {
            H->Data[Parent][0] = H->Data[Child][0];
            H->Data[Parent][1] = H->Data[Child][1];
        }
    }
    H->Data[Parent][0] = x[0];
    H->Data[Parent][1] = x[1];
}
void BuildHeap(MaxHeap H)
{
    //调整H->Data[]中的元素,是满足最大堆的有序性
    //这里假设所有H->size个元素已经存在H->Data[]中
    int i;
    //从最后一个结点的父节点开始,到根结点
    for (i = H->size / 2; i > 0;i--)
    {
        PrecDown(H, i);
    }
}
int main()
{
    int n,i;
    scanf("%d",&n);
    while(n--)
    {
    MaxHeap H;
    int num,pool,cnt,sum=0;
    //scanf("%d",&num);
    int f[2];
    scanf("%d%d",&pool,&cnt);
    H = CreateHeap(pool);
    for (i = 1; i < pool+1;i++)
    {
        scanf("%d%d",&f[0],&f[1]);
        Insert(H,f);
    }
    while(cnt--&&H->Data[1][0]>0)
    {
//        printf("%d %d\n",H->Data[1][0],H->Data[1][1]);
        sum = sum + H->Data[1][0];
        H->Data[1][0] -= H->Data[1][1];
        BuildHeap(H);
    }
    printf("%d\n",sum);
}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章