程序設計實訓

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);
}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章