第二届蓝桥杯C++B组国(决)赛真题

以下代码仅供参考,解答部分来自网友,对于正确性不能保证,如有错误欢迎评论

四方定理.
数论中有著名的四方定理:所有自然数至多只要用四个数的平方和就可以表示。
我们可以通过计算机验证其在有限范围的正确性。

对于大数,简单的循环嵌套是不适宜的。下面的代码给出了一种分解方案。

请仔细阅读,填写空缺的代码(下划线部分)。

注意:请把填空的答案(仅填空处的答案,不包括题面)存入考生文件夹下对应题号的“解答.txt”中即可。
直接写在题面中不能得分。

int f(int n, int a[], int idx)
{
    if(______________) return 1;  // 填空1
    if(idx==4)  return 0;

    for(int i=(int)sqrt(n); i>=1; i--)
    {
        a[idx] = i;

        if(_______________________)  return 1;  // 填空2
    }

    return 0;
}

int main(int argc, char* argv[])
{
    for(;;)
    {
        int number;
        printf("输入整数(1~10亿):");
        scanf("%d",&number);
        
        int a[] = {0,0,0,0};

        int r = f(number, a, 0);

        printf("%d: %d %d %d %d
", r, a[0], a[1], a[2], a[3]);
        
    }

    return 0;
}



a[0]*a[0] + a[1]*a[1] + a[2]*a[2] + a[3]*a[3] == n
f(n, a, idx + 1) == 1
来自网友:

本题满分: 9分
 
  填空1: (3分)
  n==0
  或者:0==n
 
  填空2: (6分)
  f(n-i*i, a, idx+1)
  或者:
  f(n-i*i, a, idx+1) > 0
  f(n-i*i, a, idx+1) == 1

异或加密法.
在对文本进行简单加密的时候,可以选择用一个n位的二进制数,对原文进行异或运算。
解密的方法就是再执行一次同样的操作。

加密过程中n位二进制数会循环使用。并且其长度也可能不是8的整数倍。

下面的代码演示了如何实现该功能。
请仔细阅读,填写空缺的代码(下划线部分)。

void f(char* buf, unsigned char* uckey, int n)
{

    int i;
    for(i=0; i<n; i++)
        buf[i] = buf[i] ^ uckey[i];    //异或运算,即:buf[i] ^= uckey[i]
}

int main(int argc, char* argv[])
{
    char p[] = "abcd中国人123";  // 待加密串

    char* key = "11001100010001110";  //以串的形式表达的密匙,运算时要转换为按位存储的形式。

    int np = strlen(p);
    int nk = strlen(key);
    unsigned char* uckey = (unsigned char*)malloc(np);  // unsigned char是无符号字节型,char类型变量的大小通常为1个字节(1字节=8个位)    
    // 密匙串需要按位的形式循环拼入 uckey中
    int i;
    for(i=0; i<np*8; i++)
    {
        if(key[i%nk]=='1')
            ______;  // 填空1按位或
        else
            ______;  // 填空2按位与
    }
    
    f(p, uckey, strlen(p));
    f(p, uckey, strlen(p));

    printf("%s
", p);

    free(uckey);

    return 0;
}


uckey[i/8] |= (unsigned char)0x80 >> (i%8)
uckey[i/8] &= ~((unsigned char)0x80 >> (i%8))

本题满分:14分
  
  填空1:(7分)
  uckey[i/8] |= (unsigned char)0x80 >> (i%8);    //>>表示右移位,位逻辑运算符:&按位与,|按位或,^按位异或,~取反,移位运算符:<<左移,>>右移
从数学上看,左移1位等于乘以2,右移1位等于除以2,然后再取整,移位溢出的丢弃
 
  填空2:(7分)
  uckey[i/8] &= ~((unsigned char)0x80 >> (i%8));
 
  注意所有逻辑等价形式都是正确的答案,比如可以使用左移位:
  (unsigned char)0x80 >> 2  等价于:0x01 << 5

最小公倍数、
为什么1小时有60分钟,而不是100分钟呢?这是历史上的习惯导致。
但也并非纯粹的偶然:60是个优秀的数字,它的因子比较多。
事实上,它是1至6的每个数字的倍数。即1,2,3,4,5,6都是可以除尽60。

我们希望寻找到能除尽1至n的的每个数字的最小整数。

不要小看这个数字,它可能十分大,比如n=100, 则该数为:
69720375229712477164533808935312303556800

请编写程序,实现对用户输入的 n (n<100)求出1~n的最小公倍数。

例如:
用户输入:
6
程序输出:
60

用户输入:
10
程序输出:
2520

要求考生把所有函数写在一个文件中。调试好后,存入与考生文件夹下对应题号的“解答.txt”中即可。
相关的工程文件不要拷入。
对于编程题目,要求选手给出的解答完全符合ANSI C标准,不能使用c++特性;
不能使用诸如绘图、中断调用等硬件相关或操作系统相关的API。

Java解法:

import java.math.BigInteger;
import java.util.Scanner;

public class Main {
    
    public void getResult(int n) {
        BigInteger temp1 = BigInteger.ONE;
        BigInteger temp2 = BigInteger.ONE;
        BigInteger temp3 = BigInteger.ONE;
        for(int i = 2;i <= n;i++) {
            temp1 = temp3;
            temp2 = new BigInteger(""+i);
            temp3 = temp1.gcd(temp2);
            temp3 = temp1.multiply(temp2).divide(temp3);
        }
        System.out.println(temp3);
    }
    
    public static void main(String[] args) {
        Main test = new Main();
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        test.getResult(n);
    }
}

C++解法:

解答:
最小公倍数就是所有质数的相应幂的积
比如N=10
小于10的质数有2,3,5,7
对应的最大幂是:3,2,1,1
则最小公倍数是:2^3x3^2x5^1x7^1 = 2520

 #include <iostream>
 #include <cstring>
 #include <cmath>
 using namespace std;
 
 int a[50] = {0};//存素数 
 bool vis[100];
 int b[50] = {0};//存幂次 
 
 void init_prim()//求小于100的所有素数存入数组a 
 {
      int i,j,k;
      int m = (int)(sqrt(100.0)+0.5);
      memset(vis,0,sizeof(vis));
      vis[0] = 1;
      vis[1] = 1;//必须加上,否则第一个素数别认为是1 
      for(i=2; i<=m; i++)
      if(!vis[i])
      {
           for(j=2*i; j<=100; j+=i)
                vis[j] = 1;
      }
      int t = 0;
      for(k=0; k<100; k++)
      if(!vis[k])
           a[t++] = k;
 }
      
 int main()
 {
      int i,j,k;
      init_prim();
      int n;
      //2^6 = 64,2^7 = 128;由于n最大100,幂次最大6 
     // for(i=0 ; i<100; i++)//素数没问题 
     // if(!vis[i])
     //      cout<<i<<endl;
    //  while(1);
      while(cin>>n)
      {
           memset(b,0,sizeof(b));
           for(i=0; i<=n&&a[i]<=n; i++)//”1到n素数个数小于n的一半 “不对,3有两个素数 
           {
               // cout<<a[i]<<"-----"<<endl;
                for(j=1; j<=6; j++)
                {
                     if(pow((double)a[i],(double)j)>(double)n)
                     {
                          b[i] = j -1;//b的下标不必新开  
                          break;
                     }
                     else if(pow((double)a[i],(double)j) == (double)n)//必须分开 
                     {
                           b[i] = j;
                          break;     
                     }
                }                                   
           }
           //不知道是不是pow函数的问题,把ans定义为int得出的结果出问题,double就对了 
           double ans = 1;
           for(k=0; k<i; k++)
           {
                //cout<<a[k]<<"........"<<b[k]<<endl;
                ans *= pow((double)a[k],(double)b[k]);
           }
           cout<<(int)ans<<endl;      
      }
      return 0;     
 }
 
 //该程序 到25时就溢出,ans换位long long前几个就错误啦,此时需要把pow函数换掉

 #include <iostream>
 #include <cstdio>
 #include <cstring>
 #include <cmath>
 using namespace std;
 
 const int N = 105;
 int n;
 int a[N][50];
 int b[N] = {0};
 
 void multiply()
 {
     int i,j,k;
     memset(a,0,sizeof(a));
     for(i=3; i<=100; i++)
     {
         /*
         下面的是直接按平常的乘法,乘数的一位乘以被乘数的每一位并处理进位;另外是乘数整体乘以被乘数的每一位最后统一处理进位
         */
         int temp = 0; 
         a[i][0] = 1;//很重要 
         for(j=2; j<=i; j++)
         {
             int  c = 0; 
             for(k=0; k<50; k++)//最大不超过160位 ,目前是100!,最后除以3等50 
             {
                 temp = a[i][k]*b[j] + c;
                 a[i][k] = temp%1000;
                 c = temp/1000;
             }          
         }
     }
 }
 
 void printData(int n)
 {
     int i,j,k;
     for(i=49; i>=0; i--)
     if(a[n][i])
         break;
     cout<<a[n][i];//第一个不输出前导0 
     for(j=i-1; j>=0; j--)
         printf("%03d",a[n][j]);
     cout<<endl;   
 }
 
 int main()
 {
     int i, j, k;
     for(i=0; i<N; i++)
             b[i] = i;
     for(i=2; i<N; i++)
         for(j=i+1; j<=N; j++)
         {
             if(b[j]%b[i]==0)
                 b[j] /= b[i];
             //cout<<b[j]<<endl;
         }
     //for(i=0; i<100; i++)
       //  cout<<b[i]<<endl;
     //while(1);
     multiply();
     
     while(cin>>n)
     {
         
         if(n==1||n==2)
         {
             cout<<n<<endl;
             continue;
         }
         
         printData(n);
     }
     return 0;
 }

地铁换乘、

为解决交通难题,某城市修建了若干条交错的地铁线路,线路名及其所属站名如stations.txt所示。

线1
苹果园
....
四惠东

线2
西直门
车公庄
....
建国门

线4
....

其中第一行数据为地铁线名,接下来是该线的站名。
当遇到空行时,本线路站名结束。

下一行开始又是一条新线....直到数据结束。


如果多条线拥有同一个站名,表明:这些线间可以在该站换车。

为引导旅客合理利用线路资源,解决交通瓶颈问题,该城市制定了票价策略:

1. 每条线路可以单独购票,票价不等。
2. 允许购买某些两条可换乘的线路的联票。联票价格低于分别购票。

单线票价和联合票价如 price.txt 所示。

线1 180
.....
线13 114
线1,线2 350
线1,线10 390
.....


每行数据表示一种票价
线名与票价间用空格分开。如果是联票,线名间用逗号分开。
联票只能包含两条可换乘的线路。

现在的问题是:根据这些已知的数据,计算从A站到B站最小花费和可行的换乘方案。

比如,对于本题目给出的示例数据

如果用户输入:
五棵松,奥体中心

程序应该输出:
-(线1,线10)-线8 = 565

如果用户输入:
五棵松,霍营

程序应该输出:
-线1-(线4,线13) = 440

可以看出,用户输入的数据是:起始站,终到站,用逗号分开。
程序输出了购票方案,在括号中的表示联票,短横线(-)用来分开乘车次序。
等号后输出的是该方案的花费数值。


请编程解决上述问题。
注意:
1. 我们测试您的程序时,所用数据与题目中的示例数据不同,但格式完全一样。
2. 当多个方案有相同的最小花费,输出任意一个方案即可。


要求考生把所有类写在一个文件中。
调试好后,存入与考生文件夹下对应题号的“解答.txt”中即可。
相关的工程文件不要拷入。请不要使用package语句。

Java解法

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
public class js_04 {
	public static void main(String[] args) {
		Scanner scanner=new Scanner(System.in);
		String input=null;
		String[] tmp=null;
		while(scanner.hasNextLine()){
			input=scanner.nextLine();
			tmp=input.split(",");
			new js_04(tmp[0],tmp[1]);
		}
	}
	public js_04(String start,String end){
		//解析stations.txt文件,初始化站点信息
		initStations();
		//初始化线路相连信息
		initLines();
		//解析price.txt文件,初始化价格信息
		initPrice();
		input(start,end);
		startProcess();
	}
	//起始站集合
	private List<String> start=new ArrayList<String>();
	//终点站集合
	private List<String> end=new ArrayList<String>();
	//输入起始站和终点站
	public void input(String stationA,String stationB){
		//找到该站属于哪条线
		Iterator<String> it=stationsMap.keySet().iterator();
		String stations=null;
		String line=null;
		while(it.hasNext()){
			line=it.next();
			stations=stationsMap.get(line);
			if(stations.contains(stationA+",")){
				//添加到开始线路集合
				start.add(line);
			}
			if(stations.contains(stationB+",")){
				//添加到结束线路集合
				end.add(line);
			}
		}
	}
	//开始正式处理
	public void startProcess(){
		for(String st:start){
			for(String en:end){
				Line cuStart=lines.get(st);
				cuStart.isUse=true;
				process.add(cuStart);
				nfs(cuStart,lines.get(en));
				process.remove(cuStart);
				cuStart.isUse=false;
			}
		}
		//输入最终结果
		if(minPriceProcess!=null){
			System.out.print(minPriceProcess+" = ");
			System.out.println(minPrice);
		}else{
			System.out.println("不可达");
		}
	}
	//存储遍历过程
	private List<Line> process=new ArrayList<Line>(); 
	public void nfs(Line startLine,Line endLine){
		//结束找到符合要求的路径
		if(startLine.equals(endLine)){
			calPrice();
		}else{
			//遍历所有的可连接节点
			for(Line line:startLine.connLines){
				//已经遍历过则跳过
				if(line.isUse)continue;
				line.isUse=true;
				process.add(line);
				nfs(line,endLine);
				process.remove(line);
				line.isUse=false;
			}
		}
	}
	//存储最少价钱
	private int minPrice=Integer.MAX_VALUE;
	private void calPrice(){
		length=process.size();
		String calProcss="";//存储过程
		cal(0,0,calProcss);
	}
	private int length;
	private String minPriceProcess;
	//lineIndex表示当前要处理的路线的下标
	public void cal(int lineIndex,int currPrice,String calProcess){
		if(lineIndex>=length){
			if(currPrice<minPrice){
				minPriceProcess=calProcess;
				minPrice=currPrice;
			}
			return;
		}
		if(lineIndex==length-1){
			Line line=process.get(lineIndex);
			currPrice+=line.price;
			if(currPrice<minPrice){
				minPrice=currPrice;
				minPriceProcess=calProcess+"-"+line;
			}
			return;
		}else{
			Line one=process.get(lineIndex);
			Line two=process.get(lineIndex+1);
			if(currPrice+one.price>=minPrice)return;
			cal(lineIndex+1,currPrice+one.price,calProcess+"-"+one);
			int connPrice=isConnection(one,two);
			if(connPrice!=-1){//可以相连,则考虑相连的情况
				if(currPrice+connPrice>=minPrice)return;
				cal(lineIndex+2,currPrice+connPrice,calProcess+"-("+one.name+","+two.name+")");
			}
		}
	}
	//判断两条线路是否联票,是则返回联票价钱,否则返回-1
	public int isConnection(Line one,Line two){
		String key=one.name+","+two.name;
		Integer value=connLines.get(key);
		if(value==null)return -1;
		return value;
	}
	//用于保存所有的线路信息,key为线路名,value为该线路下的所有站点
	private Map<String,String> stationsMap=new HashMap<String,String>();
	//存储线路的集合,通过路线名获得路线类对象
	private Map<String,Line> lines=new HashMap<String,Line>();
	public void initStations(){
		try {
			File file=new File("stations.txt");
			BufferedReader reader=new BufferedReader(new InputStreamReader(new FileInputStream(file)));
			StringBuilder value=new StringBuilder();
			String content=null;
			String key=null;
			boolean isHead=true;//是否是线路名
			while((content=reader.readLine())!=null){
				if("".equals(content)){//一条线路读取结束
					//将线路存储起来
					Line line=new Line();
					line.name=key;
					lines.put(key, line);
					stationsMap.put(key, value.toString());
					isHead=true;
					value.delete(0, value.length());
				}else{
					if(isHead){//第一个为线路名
						key=content;
						isHead=false;
					}else{
						value.append(content).append(",");
					}
				}
			}
			Line line=new Line();
			line.name=key;
			lines.put(key, line);
			stationsMap.put(key, value.toString());
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	//初始化线路连接情况
	public void initLines(){
		List<String> list=new ArrayList<String>(stationsMap.keySet());
		int length=list.size();
		for(int i=0;i<length;i++){	
			for(int j=i+1;j<length;j++){
				//线路名
				process(list.get(i),list.get(j));
			}
		}
	}
	//处理所有交叉线路
	public void process(String l1,String l2){
		String line1=stationsMap.get(l1);
		String line2=stationsMap.get(l2);
		String[] strs=line1.split(",");
		for(String str:strs){
			if(line2.contains(str+",")){//如果两个路线有共同站点,说明交叉
				Line line01=lines.get(l1);
				Line line02=lines.get(l2);
				line01.connLines.add(line02);
				line02.connLines.add(line01);
				return;
			}
		}
	}
	//联票路线
	private Map<String,Integer> connLines=new HashMap<String,Integer>();
	//初始化价钱列表,获得联票信息
	public void initPrice(){
		try {
			File file=new File("price.txt");
			BufferedReader reader=new BufferedReader(new InputStreamReader(new FileInputStream(file)));
			String content=null;
			String[] keyValue=null;
			int price=0;
			while((content=reader.readLine())!=null){
				keyValue=content.split(" ");
				price=Integer.valueOf(keyValue[1]);
				if(keyValue[0].contains(",")){//联票
					connLines.put(keyValue[0], price);
				}else{//单条路线
					lines.get(keyValue[0]).price=price;
				}
			}
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	//自定义线路类
	class Line{
		//线路名
		public String name;
		//是否遍历过
		public boolean isUse;
		//和该路线交叉的路线
		List<Line> connLines=new ArrayList<Line>();
		//该路线的价钱
		public int price;
		@Override
		public boolean equals(Object obj) {
			return this.name.equals(((Line)obj).name);
		}
		@Override
		public String toString() {
			return this.name;
		}
	}
}

C++:

#include<iostream>
using namespace std;
#define LEN 50
typedef struct stations{
    char name[20];
    int len;
    int roads[50];
    struct stations *left;
    struct stations *right;
}Stations;

typedef struct etree{
    int value;
    int roadNum;
    struct etree *father;
    int childnum;
}ETree;

typedef struct queue{
    ETree *tie;
    struct queue *next;
}Queue;

void pushQueue(Queue &head, ETree *&etree){
    Queue *p=head.next,*q=&head;
    while(p!=NULL &&  (p->tie->value<etree->value)){
        q=p;
        p=p->next;
    }
    q->next=(Queue*)malloc(sizeof(Queue));
    q->next->tie=etree;
    q->next->next=p;
}
void freeEtree(ETree *q){
    ETree *p;
    while(q->childnum==0){
        p=q;
        q=q->father;
        free(p);
        if(q!=NULL)
            q->childnum--;
        else
            break;
    }
}

void freeAll(Stations *&head){
    if (head!=NULL){
        freeAll(head->left);
        freeAll(head->right);
        free(head);
    }
}

void showBest(ETree *h,int price[][LEN],char roadName[][20],int roadNum){
    if(h!=NULL){
        if (h->faher==NULL){
            printf("%s",roadName[h->roadNum]);
        }
        else{
            int j;
            j=h->roadNum;
            if (h->value==(price[j][j]+h->father->value)){
                showBest(h->father,price,roadName,roadNum);
                if (price[j][roadNum]){
                    printf("-(%s,%s)",roadName[j],roadName[price[j][roadNum]-1]);

                }
                else
                    printf("-%s",roadName[j]);
            }
            else{
                showBest(h->father->father,price,roadNme,roadNum);
                printf("-(%s,%s)",roadName[h->father->roadNum],roadName[j]);
            }
        }
    }
}

inline int compares(char s1[],int n1,chr s2[],int n2){
    if (n1!=n2)
        return n1-n2;
    return strcmp(s1,s2);
}
boll findStation(Stations* &head,Stations* &p,char s[]){
    int len=strlen(s);
    int t;
    Stations q;
    p=head;
    while (n!=NULL){
        q=p;
        t=compares(s,len,p->name,p->len);
        if (t<0)
            p=p->left;
        else
            retrn true;
    }
    p=q;
    return false;
}

void insert(Stations* &head,char s[],int road,int price[][LEN]{
    Stations *p,*q;
    int t;
    t=strlen(s);
    if(s[t-1]=='
')
        s[t-1]='';
    if(head==NULL){
        p=(Stations *)malloc(sizeof(Stations));
        p->left=NULL;
        p->rght=NULL;
        strcpy(p->name,s);
        p->len=strlen(s);
        p->road[0]=1;
        p->road[1]read;
        head=p;
    }
    else{
        if (findStation(head,p,s)){
            p->roads[0]++;
            t=p->roads[0];
            p->roads[t]=road;
            for(t--;t>0,t--){
                price[p->road[t]][road]=-1;
                price[road][p->road[t]]=-1;
            }
        }
        else{
            q=p;
            p=(Stations *)malloc(sizeof(Stations));
            p->left=NULL;
            p->right=NULL;
            strcpy(p->name,s);
            p->len=strlen(s);
            p->road[0]=1;
            p->road[1]=road;
            t=compares(s,p->len,q->name,q->len);
            if(t<0)
                q->left=p;
            else
                q->right=p;
        }
    }
}

int GetRoadNum(char *r,char roadName[][20],int road Num){
    for (int i=0;i<roadNum;i++)
        if (strcmp(roadName[i],r)==0)
            return i;
        return 0;
}

void main()
{
    //[roadnum][roadnum+1]
    int price[LEN][LEN]={0};
    char roadName[LEN][20];
    int i,j,k,t;
    char line[20];
    int roadNum;
    Stations *head=NULL;
    FILE *fp;
    if((fp=fopen("stations.xt","r"))==NULL){
        printf("找不到stations文件
");
        return;
    }
    roadNum=0;
    while(!feof(fp)){
        fscanf(fp,"%s%*c",roadName[roadNum]);
        fgets(line,19,fp);
        while(!feof(fp)&&line[0]!='
'){
            insert(head,line,roadNum,price);
            fgets(line,19,fp);
        }
        roadNum++;
    }
    roadNum++;
}
insert(head,line,roadNum-1,price);
fclose(fp);
if ((fp=fopen("price.txt","r"))==NULL){
    printf("找不到price文件");
}
while (!feof(fp)){
    fscanf(fp,"%s,line);
    fscanf(fp,"%d",&k);
    for(t=0;line[t]!=''&&line[t]!=",";t++);
    if (line[t]==','){
        line[t]='';
        i=GetRoadNum(line,roadName,roadNum);
        j=GetRoadNum(line+t+1,roadName,roadNm);
        price[i][j]=k;
        price[j][i]=k;
        if (price[i][i]>k){
            price[i][roadNum]=j+1;
        }
        if (price[j][j]>k){
            price[j][j]=k;
            price[j]roadNum]=i+1;
        }
    }
    else{
        i=GetRoadNum(line,roadName,roadNum);
        price[i][i]=k;
    }
}

fclose(fp);

char starts[20]={"五棵松"},ends[20]="奥体中心"};
Stations *sroad,*eroad;
Queue Qhead, *h;
Etree *p,*q;
while(true){
    char Flag[LEN]={0};//为-1表示目标,为0表示尚未发生过扩展
    Qhead.next=NULL;
    Qhead.tie=NULL;
    scanf("%[^,
]s",starts);
    if (getchar()!=',')
        break;
    scanf("%[^
]s",ends);
    getchar();
    if (!findStation(head,sroad,starts)){
        printf("未找到%s的匹配项
",starts);
        continue;
    }
    if (!findStation(head,eroad,ends)){
        printf("未找到%s的匹配项
",ends);
        continue;
    }
    for (i=1;i<=sroad->roads[0];i++){
        p=(ETree*)malloc(sizeof(ETree));
        p->father=NULL;
        p->childnum=0;
        p->roadNum=sroad->roads[i];
        p->value=price[p->roadum][p->roadNum];
        pushQueue(Qhead,p);
    }
    for (i=1;i<=eroad->roads[0];i++){
        Flag[eroad->roads[i]]=-1;
    }
    while(Qhead.next!=NULL){
        h=Qhead.next;
        q=h->tie;
        if (Flag[q->roadNum]==-1){
            break;
        }
        Qhuad.next=Qhead.next->next;
        i=q->roadNum;
        if (Flag[i]!=1){
            for(j=0;j<roadNum;j++){
                if (price[i][j]){
                    q->childnum++;
                    p=(ETree*)malloc(sizeof(ETree));
                    p->father=q;
                    p->childnum=0;
                    p->roadNum=j;
                    k=price[j][j]>0){
                        if(price[i][j]>0){
                            if(q->father!=NULL)
                                t=price[i][j]+q->father->value;
                            else
                                t=price[i][j];
                            if (k>t)
                                k=t;
                        }
                        p->value=k;
                        pushQueue(Qhead,p);
                    }
                }
                Flag[i]=1;
            }
            freeETree(h->tie);
            free(h);
        }
        if (Qhead.next!=NULL){
            showBest(q,price,roadName,roadNum);
            printf("=%d
",q->value);
        }
        else
            printf("此路不通
");
        for(;Qhead.next!=NULL;){
            h=Qead.next;
            Qhead.nexQhead.next->next;
            freeETree(h->tie);
            free(h);
        }
    }
    freeAll(head);
}

连通问题、
BMP是常见的图像存储格式。
如果用来存黑白图像(颜色深度=1),则其信息比较容易读取。

与之相关的数据:

(以下偏移均是从文件头开始)
偏移:10字节, 长度4字节: 图像数据真正开始的位置。
偏移:18字节, 长度4字节: 位图的宽度,单位是像素。
偏移:22字节, 长度4字节: 位图的高度,单位是像素。

从图像数据开始处,每个像素用1个二进制位表示。
从图片的底行开始,一行一行向上存储。

Windows规定图像文件中一个扫描行所占的字节数必须是4字节的倍数,
不足的位均以 0 填充。例如,图片宽度为45像素,实际上每行会占用
8个字节。

可以通过Windows自带的画图工具生成和编辑二进制图像。
需要在“属性”中选择“黑白”,指定为二值图像。
可能需要通过 查看 | 缩放 | 自定义… 把图像变大比例一些,
更易于操作。

图像的左下角为图像数据的开始位置。白色对应1,黑色对应0

我们可以定义:两个点距离如果小于2个像素,则认为这两个点连通。
也就是说:以一个点为中心的九宫格中,围绕它的8个点与它都是连通的。
如:t1.bmp 所示,左下角的点组成一个连通的群体;
而右上角的点都是孤立的。

        in.bmp                                t1.bmp

程序的目标是:根据给定的黑白位图,分析出所有独立连通的群体,
输出每个连通群体的面积。所谓面积,就是它含有的像素的个数。

输入数据固定存在in.bmp中。

如示例的in.bmp,
程序应该输出:
81
133

该输出表示:共有4个连通群体。
输出的连通体面积间的顺序可以随意。

请编程解决上述问题。

我们测试程序的时候,会使用不同的in.bmp文件。

要求考生把所有类写在一个文件中。
调试好后,存入与考生文件夹下对应题号的“解答.txt”中即可。
相关的工程文件不要拷入。请不要使用package语句。

在这里插入图片描述
在这里插入图片描述

这题要读入图片文件数据,感觉头大啊,此前做的题,几乎没有遇到要读取文件中的数据,而现在竟然还碰到了读取图片的数据,看到此题的核心:即使用DFS求取连通图的问题,并且返回每一个连通图中包含的顶点个数,但是对于此题处理读取数据的问题,就没有仔细去探究,下面贴出一段网友的C语言代码,以作参考:

include<stdio.h> 
#include<stdlib.h> 
#include<malloc.h> 
#include<string.h> 

void main(){ 
int i,j,k,m; 
int width,height,start,world; 
int *bmp,*Lcount; 
bool *Lflag; 
FILE *fp; 
if((fp=fopen("in1.bmp","rb"))==NULL){ 
printf("文件打开失败"); 
return; 
}
fseek(fp,10L,0); 
fscanf(fp,"%4c",&start); // 4c表示该数据占4个字节
// printf("start = %d
",start); 
fseek(fp,18,0); 
fscanf(fp,"%4c",&width); 
// printf("width = %d
",width); 
fseek(fp,22,0); 
fscanf(fp,"%4c",&height); 
// printf("height = %d
",height); 
bmp = (int*)malloc((width+2)*sizeof(int)); 
memset(bmp,0,(width+2)*sizeof(int)); 
Lcount = (int*)malloc(width*sizeof(int)); 
memset(Lcount,0,width*sizeof(int)); 
Lflag = (bool*)malloc(width*sizeof(bool)); 
memset(Lflag,0,width*sizeof(bool)); 
Lcount--; 
Lflag--; 
fseek(fp,start,0); 
world = ( width%32 ? width/32+1 : width/32 )*4; 
int last,i1,i2,i3; 
int eCount = 0 
for(i=0 i<height i++ ){ 
char c; 
k=1; 
last=0; 
for(j=0 j<world j++){ 
fscanf(fp,"%c",&c); 
for(m = 7 m >= 0 && k<=width m-- ){ 
if( !( 1<<m & c ) ){ 
//printf("*"); 
if(bmp[k]){ 
last = bmp[k]; 
Lcount[last]++; 
Lflag[last] = true 
}
else{ 
i1 = last ? last : bmp[k-1] 
i3 = bmp[k+1] 
last = 0; 
if( i1 || i3){ 
if( i1 && i3 && ( i1 != i3 ) ){//确定需要连接
Lcount[i1] += Lcount[i3] 
Lcount[i3]=0; 
for(i2=1;i2<=width i2++){ 
if(bmp[i2]==i3) 
bmp[i2] = i1; 
} 
} 
else{ 
if(!i1) 
i1=i3; 
} 
bmp[k] = i1 
Lcount[i1]++; 
Lflag[i1] = true 
} 
else{//插入
for(i2=1;Lcount[i2];i2++); 
Lcount[i2]=1; 
bmp[k] = i2 
Lflag[i2] = true 
} 
} 
} 
else{ //printf(" "); 
last = bmp[k] 
bmp[k] = 0 
} 
k++; 
} 
} 
//printf("
"); 
for(i2=1;i2<=width;i2++){ 
if(Lcount[i2] && !Lflag[i2] ){ 
printf("%d
",Lcount[i2]); 
Lcount[i2] = 0 
eCount++; 
} 
Lflag[i2]=false; 
} 
} 
fclose(fp); 
free(Lflag+1); 
free(Lcount+1); 
free(bmp); 
printf("count=%d
",eCount); 
}
原文地址:https://www.cnblogs.com/a1439775520/p/13078699.html