编程训练


图片整理

描述

Lily上课时使用字母数字图片教小朋友们学习英语单词,每次都需要把这些图片按照大小(ASCII码值从小到大)排列收好。请大家给Lily帮忙,通过C语言解决。

输入


Lily使用的图片包括"A"到"Z"、"a"到"z"、"0"到"9"。输入字母或数字个数不超过1024。

输出


Lily的所有图片按照从小到大的顺序输出

样例输入 Ihave1nose2hands10fingers
样例输出 0112Iaadeeefghhinnnorsssv


#include <iostream>
#include <algorithm>
#include <string>
using namespace  std;
int main()
{
	string n;
	cin >> n;
	sort(n.begin(), n.end());
	cout << n;

}
或者
#include<stdio.h> 
#include<string.h> 
#include<stdlib.h>
char s[10000],i,n;
int cmp(const void *a,const void *b)
{ 
     return(*(char *)a-*(char *)b); //升序
}
int main() 
{ 
     scanf("%s",s); 
     n=strlen(s); 
     qsort(s,n,sizeof(s[0]),cmp);     
     printf("%s",s);           
     return 0; 
}


计算字符个数

题目描述

写出一个程序,接受一个有字母和数字以及空格组成的字符串,和一个字符,然后输出输入字符串中含有该字符的个数。不区分大小写。


输入


输入一个有字母和数字以及空格组成的字符串,和一个字符。


输出


输出输入字符串中含有该字符的个数。


样例输入 ABCDEF A
样例输出 1

#include <iostream>
#include <stdio.h>
#define MAXSIZE 100
using namespace std;

int getcharcount(char c[], char ch){
	char* p = c;
	char chx;
	int i = 0;
	
	while(*p != '\0'){
		if(ch>='A' && ch<='Z')
			chx = ch + 32;
		else
			chx = ch - 32;
		
		if(*p == ch || *p ==chx)
			i++;
		
		p++;
		
	}
	
	return i;
}

int main(void)
{		    
	char c[MAXSIZE];
	char ch;
	int count;
		
    gets(c);
    ch = getchar();
    
    count = getcharcount(c, ch); 
    cout << count << endl;
    
	return 0;
}


字符串反转

描述

写出一个程序,接受一个字符串,然后输出该字符串反转后的字符串。例如:

输入

输入N个字符

输出

输出该字符串反转后的字符串

样例输入 abcd
样例输出 dcba

#include <iostream>
#include <string.h> 
#define MAXSIZE 1024
using namespace std;


int main(void)
{		    
    char c[MAXSIZE];			
    int len = 0;
    gets(c);
    
    len = strlen(c);
    for(int i=len-1; i>=0; i--){
		cout << c[i];
	}
    cout << endl;
    
	return 0;
}

#include <iostream>
#include <string>
#include<iterator>

using namespace std;

int main()
{
string str;
getline(cin,str);
if(str.empty())
	return 0;
string::iterator it=str.end()-1;
for(;it!=str.begin();it--)
{
        cout<<*it;
}
        cout<<*it;
}

名字漂亮度

描述

给出一个名字,该名字有26个字符串组成,定义这个字符串的“漂亮度”是其所有字母“漂亮度”的总和。
每个字母都有一个“漂亮度”,范围在1到26之间。没有任何两个字母拥有相同的“漂亮度”。字母忽略大小写。
给出多个名字,计算每个名字最大可能的“漂亮度”。

输入

整数N,后续N个名字
N个字符串,每个表示一个名字

输出


每个名称可能的最大漂亮程度

样例输入 2 zhangsan lisi
样例输出 192 101

#include <iostream>  
#include <cctype>  
#include <algorithm>  
using namespace std;  
  
int Name_Beauty(char a[])  
{  
      int b[26]={0};  
      for(int i=0;a[i]!='\0';++i)  
      {  
            a[i]=tolower(a[i]);  
            b[a[i]-97]++;  
      }  
      sort(b,b+26);  
      int sum=0;  
      for(int i=0;i<26;++i)  
            sum+=(i+1)*b[i];  
      return sum;  
  
}  
  
int main()  
{  
    int n=0;  
    cin>>n;  
    char array[100][100];  
    getchar();  
    for (int i=0;i<n;++i)  
      gets(array[i]);  
    for (int i=0;i<n;++i)  
      cout<<Name_Beauty(array[i])<<endl;  
    return 0;  
}  



合唱队


描述

计算最少出列多少位同学,使得剩下的同学排成合唱队形

说明:

N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队形。
合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2…,K,他们的身高分别为T1,T2,…,TK, 则他们的身高满足存在i(1<=i<=K)使得Ti<T2<......<Ti-1<Ti>Ti+1>......>TK。
你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。

输入


整数N

一行整数,空格隔开,N位同学身高

输出

最少需要几位同学出列

样例输入 8 186 186 150 200 160 130 197 200
样例输出 4

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void getLISA(int *pArr, int len, int* pRes); //求最长上升子序列
void getLDSA(int *pArr, int len, int* pRes); //求最长下降子序列---或者说从后往前的上升序列

void main()
{
    int arr[500],Lis[500],Lds[500];
    int len, i, t = 0,index;
    scanf("%d", &len);
    for (i = 0; i < len; i++)
        scanf("%d",&arr[i]);
    getLISA(arr,len,Lis);
    getLDSA(arr, len, Lds);
    for (i = 0; i < len; i++)
        if (t < Lis[i] + Lds[i])
        {
            t = Lis[i] + Lds[i];
            index = i;
        }
    printf("%d\n", len - Lis[index] - Lds[index]+1);
//  system("pause");
}
void getLISA(int *pArr, int len,int *pRes)
{
    int i, j, k;
    for (i = 0; i < len; i++)
    {
        pRes[i] = 1;
        for (j = 0; j < i; j++)
            if (pArr[i]>pArr[j] && pRes[i] < (pRes[j] + 1))
                pRes[i] = pRes[j] + 1;
    }
}
void getLDSA(int *pArr, int len, int *pRes)
{
    int i, j, k;
    for (i = len-1; i >=0; i--)
    {
        pRes[i] = 1;
        for (j = len-1; j >i;j--)
            if (pArr[i]>pArr[j] && pRes[i] < (pRes[j] + 1))
                pRes[i] = pRes[j] + 1;
    }
}


字符串加解密


题目描述


1、对输入的字符串进行加解密,并输出。

2加密方法为:

当内容是英文字母时则用该英文字母的后一个字母替换,同时字母变换大小写,如字母a时则替换为B;字母Z时则替换为a;

当内容是数字时则把该数字加1,如0替换1,1替换2,9替换0;

其他字符不做变化。

3、解密方法为加密的逆过程。



接口描述:

实现接口,每个接口实现1个基本操作:

void Encrypt (char aucPassword[], char aucResult[]):在该函数中实现字符串加密并输出

说明:

1、字符串以\0结尾。

2、字符串最长100个字符。



int unEncrypt (char result[], char password[]):在该函数中实现字符串解密并输出

说明:

1、字符串以\0结尾。

2、字符串最长100个字符。



输入

输入说明
输入一串要加密的密码
输入一串加过密的密码


输出

输出说明
输出加密后的字符
输出解密后的字符

样例输入 abcdefg BCDEFGH
样例输出 BCDEFGH abcdefg


#include <iostream>
#include <cctype>
#include <cstdlib>
using namespace std;

void Encrypt (char aucPassword[], char aucResult[]){    
	int i=0;    
	while(aucResult[i]!='\0'){        
		if(isalpha(aucResult[i])){            
			if(islower(aucResult[i]))                
				aucPassword[i]=(static_cast<int>((aucResult[i]-'a'+1)))%26+'A';            
			else                
				aucPassword[i]=(static_cast<int>((aucResult[i]-'A'+1)))%26+'a';        
		}        
		else if(isalnum(aucResult[i]))            
			aucPassword[i]=(static_cast<int>((aucResult[i]-'0'+1)))%10+'0';        
		else            
			aucPassword[i]=aucResult[i];        
		i++;    
	}    
	aucPassword[i]='\0';
}

int unEncrypt (char result[], char password[]){    
	int i=0;
    while(password[i]!='\0'){
	   	if(isalpha(password[i])){
			if(islower(password[i]))                
				result[i]=(static_cast<int>((password[i]-'a'+25)))%26+'A';
			else                
				result[i]=(static_cast<int>((password[i]-'A'+25)))%26+'a';        
			}        
		else if(isalnum(password[i]))            
			result[i]=(static_cast<int>((password[i]-'0'+9)))%10+'0';        
		else            
			result[i]=password[i];
		i++;    
	}    
	result[i]='\0';    
	return 0;
}

int main(){
       char result1[101],password1[101];
	char result2[101],password2[101];    
	while(cin>>result1>>password2){        
		Encrypt(password1,result1);        
		unEncrypt(result2,password2);        
		cout<<password1<<endl;        
		cout<<result2<<endl;    
	}    
	return 0;
}

判断两个IP是否属于同一子网

描述

子网掩码是用来判断任意两台计算机的IP地址是否属于同一子网络的根据。
子网掩码与IP地址结构相同,是32位二进制数,其中网络号部分全为“1”和主机号部分全为“0”。利用子网掩码可以判断两台主机是否中同一子网中。若两台主机的IP地址分别与它们的子网掩码相“与”后的结果相同,则说明这两台主机在同一子网中。

示例:
I P 地址  192.168.0.1
子网掩码  255.255.255.0

转化为二进制进行运算:

I P 地址 11010000.10101000.00000000.00000001
子网掩码 11111111.11111111.11111111.00000000

AND运算
    11000000.10101000.00000000.00000000

转化为十进制后为:
    192.168.0.0



I P 地址  192.168.0.254
子网掩码  255.255.255.0


转化为二进制进行运算:

I P 地址 11010000.10101000.00000000.11111110
子网掩码 11111111.11111111.11111111.00000000

AND运算
     11000000.10101000.00000000.00000000

转化为十进制后为:
     192.168.0.0

通过以上对两台计算机IP地址与子网掩码的AND运算后,我们可以看到它运算结果是一样的。均为192.168.0.0,所以这二台计算机可视为是同一子网络。

/*
* 功能: 判断两台计算机IP地址是同一子网络。
* 输入参数: String Mask: 子网掩码,格式:“255.255.255.0”;
* String ip1: 计算机1的IP地址,格式:“192.168.0.254”;
* String ip2: 计算机2的IP地址,格式:“192.168.0.1”;
*

* 返回值: 0:IP1与IP2属于同一子网络; 1:IP地址或子网掩码格式非法; 2:IP1与IP2不属于同一子网络
*/
public int checkNetSegment(String mask, String ip1, String ip2)
{
/*在这里实现功能*/
return 0;
}

输入

输入子网掩码、两个ip地址

输出

得到计算结果

样例输入 255.255.255.0 192.168.224.256 192.168.10.4
样例输出 1

#include <iostream>
#include <string>
#include <cstdlib>
#include <vector>
using namespace std;
bool checked_ip(string ip,vector<int> &vip){
    vector<string> part;    
	string::size_type ip_size=ip.size();    
	int pointCount=0;    
	int i,num;    
	string::size_type index=0;    
	string::size_type prePoint=0;    
	while((index=ip.find_first_of('.',index))!=string::npos)    
	{        
		if(index>prePoint)            
			part.push_back(ip.substr(prePoint,index-prePoint));        
		++index;        
		prePoint=index;        
		++pointCount;    
	}    
	if(prePoint<ip_size)        
		part.push_back(ip.substr(prePoint));    
	if(part.size()!=4)        
		return false;    
	for(i=0;i<4;i++)    
	{        
		num=atoi(part[i].c_str());        
		vip.push_back(num);
		if(num<0||num>255)            
			return false;    
	}    
	return true;
}

bool checked_mask(string mask,vector<int> &vmask){
    return checked_ip(mask,vmask);
}

bool checked_same(vector<int> vip1,vector<int> vip2,vector<int> vmask){
    int i;    
	int r1,r2;    
	for(i=0;i<4;i++)
	{
		r1=vip1[i]&vmask[i];        
		r2=vip2[i]&vmask[i];        
		if(r1!=r2)      
		    return false;    
		}    
		return true;
}

int checkNetSegment(string mask, string ip1, string ip2){
    vector<int> vip1;    
	vector<int> vip2;    
	vector<int> vmask;    
	if(checked_ip(ip1,vip1)&&checked_ip(ip2,vip2)&&checked_mask(mask,vmask))
	{        
		if(checked_same(vip1,vip2,vmask))     
		    return 0;        
		else           
			return 2;    
	}   
	else        
		return 1;
}
	
int main(){    
	string mask,ip1,ip2;   
	while(cin>>mask>>ip1>>ip2)    
	{    
	    cout<<checkNetSegment(mask,ip1,ip2)<<endl;
	}   
	return 0;
}


连连看-判断两个图案是否可以消去

题目描述

给定一个连连看棋盘,棋盘上每个点有各种图案(用非0数字表示),输入棋盘上的任意两个坐标,判断这两个坐标对应的图案是否可以消除,消除的条件是图案相同且图案间连线的转角数不得超过

1    3    3    4

0    6    0    0

4    0    2    1

6    0    4    2

图中,(0,1)(0,2)中的3没有转角可以消去,(1,1)(3,0)中的6有一个转角可以消去,(2,0)(3,2)中的4有两个转角可以消去,而(0,0)(23)中的1不能消去。


输入

输入为连续的整数,第1个数为棋盘行数m,第2个数为棋盘列数n,然后依次是m*n个棋盘数据(先行后列),最后,是两个坐标对应的行号和列号,mn列的棋盘,共计输入m*n+6个数。


输出

如果图案不能消除,输出0;如果图案可以消除,输出消除路线上图案个数(包含输入的两个图案,不考虑有多条可消除路径的情况)。


样例输入

4,4,1,3,3,4,0,6,0,0,4,0,2,1,6,0,4,2,2,0,3,2

样例输出

4


#include <iostream>
#include <stdio.h>

int **data;
int m, n, ans;
int start_x, start_y, end_x, end_y;
int move[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
 
int dfs(int x, int y, int count, int gj, int dir)
{
	if (gj > 2)
		return 0;
    if (x == end_x && y == end_y)
    {
        ans = count;
        return 1;
    }
    int x1, y1;
    if (count > 1)  //优先考虑上一步和当前步的方向保持一致
    {
    	x1 = x + move[dir][0];
        y1 = y + move[dir][1];
        if (x1 >= 0 && x1 < m && y1 >= 0 && y1 < n && !data[x1][y1])
        {
            if (dfs(x1, y1, count + 1, gj, dir))
                return 1;
        }
    }
    for (int i = 0; i < 4; i++)
    {
        if (count > 1 && i == dir)
            continue;
        x1 = x + move[i][0];
        y1 = y + move[i][1];
        if (x1 >= 0 && x1 < m && y1 >= 0 && y1 < n &&
            !data[x1][y1] && (count == 1 || ((i + 2) % 4) != dir))  //无须考虑当前步方向与前一步方向相反
        {
            if (dfs(x1, y1, count + 1, (i == dir || count == 1) ? gj : gj + 1, i))
                return 1;
        }

    }
    return 0;
 }
 int main(void)
 {		
    char temp;
    int i, j;

    std::cin >> m >> temp >> n >> temp;
    data = new int *[m];
   	for (i = 0; i < m; i++)
        data[i] = new int[n];

    for (i = 0; i < m; i++)
        for (j = 0; j < n; j++)
            std::cin >> data[i][j] >> temp;
    std::cin >> start_x >> temp >> start_y >> temp >> end_x >> temp >> end_y;
    ans = 0;
    data[end_x][end_y] = 0;
    dfs(start_x, start_y, 1, 0, 0);
    std::cout << ans << std::endl;
    return 0;
}


输入一行字符,分别统计出包含英文字母、空格、数字和其它字符的个数输入


输入

一行字符串,可以有空格

输出

统计其中英文字符,空格字符,数字字符,其他字符的个数

样例输入 1qazxsw23 edcvfr45tgbn hy67uj m,ki89ol.\\/;p0-=\\][
样例输出 26 3 10 12


#include <iostream>
using namespace std;
int main()
{
     char c;
     int al=0,sp=0,nu=0,other=0; 
      
     while(cin.get(c))
     {
             if(c=='\n')
                        break;
             if((c>='A' && c<='Z')||(c>='a' && c<='z'))
                  al++;
             else if(c>='0'&&c<='9')
                 nu++;
             else if(c==' ')
                 sp++;
             else 
                  other++;
     }
     cout<<al<<endl<<sp<<endl<<nu<<endl<<other<<endl;
     system("pause");
     return 0;
}

或者


#include <iostream>
using namespace std;
int main()
{
     char c;
     int al=0,sp=0,nu=0,other=0; 
      
     while(cin.get(c))
     {
             if(c=='\n')
                break;
             if(isalpha(c))
                  al++;
             else if(isdigit(c))
                 nu++;
             else if(isspace(c))
                 sp++;
             else 
                  other++;
     }
     cout<<al<<endl<<sp<<endl<<nu<<endl<<other<<endl;
     system("pause");
     return 0;
}


构造回文

题目描述

给定一个字符串s,你可以从中删除一些字符,使得剩下的串是一个回文串。
如何删除才能使得回文串最长呢?输出需要删除的字符个数。

输入描述:


输入数据有多组,每组包含一个字符串s,且保证:1<=s.length<=1000.

输出描述:

对于每组数据,输出一个整数,代表最少需要删除的字符个数。

输入例子:
abcda
google

输出例子:
2
2

#include<iostream>
#include<string>
#include<algorithm>
using namespace std;

const int MAX = 1001;
int MaxLen[MAX][MAX]; //最长公共子序列,动态规划求法

int maxLen(string s1, string s2){
    int length1 = s1.size();
    int length2 = s2.size();
    for (int i = 0; i <= length1; ++i)
        MaxLen[i][0] = 0;
    for (int i = 0; i <= length2; ++i)
        MaxLen[0][i] = 0;

    for (int i = 1; i <= length1; ++i)
    {
        for (int j = 1; j <= length2; ++j)
        {
            if (s1[i-1] == s2[j-1]){
                MaxLen[i][j] = MaxLen[i-1][j - 1] + 1;
            }
            else
            {
                MaxLen[i][j] = max(MaxLen[i - 1][j], MaxLen[i][j - 1]);
            }
        }
    }

    return MaxLen[length1][length2];
}

int main(){
    string s;
    while (cin >> s){
        int length = s.size();
        if (length == 1){
            cout << 1 << endl;
            continue;
        }
        //利用回文串的特点
        string s2 = s;
        reverse(s2.begin(),s2.end());
        int max_length = maxLen(s, s2);
        cout << length - max_length << endl;
    }
    return 0;
}

构造回文

题目描述


给出一个数字序列,允许使用一种转换操作:选择任意两个相邻的数,然后从序列移除这两个数,并用这两个数字的和插入到这两个之前的位置(只插入一个和)。

现在对于所给序列要求出最少需要多少次操作可以将其变成回文序列。


输入:

输出为两行,第一行为序列长度 n (1 <= n <=50),第二行为序列中的n个整数 item[i] (1 <= item[i] <= 1000),以空格分隔。

import java.util.ArrayList;
import java.util.Scanner;

public class Main3{
    static int count=0;
	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		 Scanner in=new Scanner(System.in);
         while(in.hasNext()){
        	 int n=in.nextInt();
        	 //int[] items=new int[n];
        	 count=0;
        	 ArrayList<Integer> list=new ArrayList<>();
        	 for(int i=0;i<n;i++){
        		 list.add(in.nextInt());
        		 //items[i]=in.nextInt();
        	 }
        	 huiWen(list);
        	 System.out.println(count);
        	 
           
         }
	}
	static void huiWen(ArrayList<Integer> list){
		int n=list.size();
		
		for(int i=0;i<n/2;i++){
			if(list.get(i)>list.get(n-1-i)){
				int tem=list.get(n-1-i)+list.get(n-2-i);
				list.remove(n-1-i);
				list.remove(n-2-i);
				list.add(tem);
				huiWen(list);
				count++;
				break;
			}else if(list.get(i)<list.get(n-1-i)){
				int tem=list.get(i)+list.get(i+1);
				list.remove(i);
				list.remove(i);
				list.add(i,tem);
				count++;
				huiWen(list);
				break;
			}
		}
	}

}

Log转换器

描述:

机器人总控中心监控机器人之间的对话交流信息,发现批次为R2D2机器人偷偷转换了语言中枢的形式,他们以倒序的形式发出信息。其他机器人正常。请整理所有机器人的对话信息。


输入:

一条对话的格式为:[机器人名称]:“信息内容”

1)交流信息由多个机器人的多条对话组成。

2)信息内容可以包含各种字符,除去 “

3)机器人名称由 XXXX-YYYY两部分组成,前一部分是姓名,后一部分是批次号,均是大小写字母和数字组成,长度不限。

4)输入字符串包含尾0的总长度不超过1024


输出:

输出字符串的格式和输入保存一致,仅R2D2批次的“信息内容”调整成正确顺序


样例输入:[JACK-R1D1]:"ABCD12345".[Joshua-R2D2]:"321Aa!".

样例输出:[JACK-R1D1]:"ABCD12345".[Joshua-R2D2]:"!aA123".


#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

using namespace std; 

//字符串分割函数
vector<string> split(string str,string pattern)
{
  string::size_type pos;
  vector<string> result;
  str+=pattern;
  int size=str.size();
 
  for(int i=0; i<size; i++)
  {
    pos=str.find(pattern,i);
    if(pos<size)
    {
      std::string s=str.substr(i,pos-i);
      result.push_back(s);
      i=pos+pattern.size()-1;
    }
  }
  return result;
}
 
int main()
{
  string str;
  string::size_type pos = 0;
  cout << "Please input str:" << endl;

  getline(std::cin,str);
  string pattern;
  cout << "Please input pattern:" << endl;

  getline(cin,pattern);
  vector<string> result=split(str,pattern);
  cout<<"The result:"<<endl;
  
  for(int i=0; i<result.size(); i++)
  {
    if((pos = result[i].find("R2D2")) != string::npos)
    	reverse(result[i+1].begin(),result[i+1].end());  	   	
  }
  
  for(int i=0; i<result.size()-1; i++)
  {
	cout << result[i] << "\"";    	
  }
  cout << result[result.size()-1] << endl;
 
  return 0;
}



城市规划

描述

为了进行城市规划,需要计算一个居住区的住宅数目。该居住聚集区俯视图已经制作好,并划分成 n*m个网格。如果某个网格单元具有屋顶的一部分,则向其赋值1,如果是块空地则赋值0.由值为1相邻网格单元组成的簇认定为一个单独住宅。对角放置的值为1的网格则不被视为属于同一住宅/屋顶。


输入

n 表示输入数组的行数

m 表示输入数组的列数

输入 n*m 数组


输出

返回一个表示住宅总数目的整数


输入示例

3

3

0 1 1

1 0 1

1 1 0


输出示例

2


方法一:使用并查集

#include <iostream>
#include <sstream>        
#include <string>

using namespace std;

int find(int *father, int n){
    int p = n;
    while(p != father[p]){
        p = father[p];
    }
    
    int i=n,j;
    while(i != p){
        j = father[i];
        father[i]=p;
        i=j;
    }
    return p;
}

void unionFather(int *father,int num1, int num2){
    int p1 = find(father, num1);
    int p2 = find(father, num2);
    if(p1 != p2){
        if(p1 < p2){
            father[p2] = p1;
        }else{
            father[p1] = p2;
        }
    }
}

int countHomes(int **grid, int n, int m)
{
    // WRITE YOUR CODE HERE
    int *father = new int[m*n];
    for(int i = 0; i<n; ++i){
        for(int j = 0; j < m; ++j){
            father[i*m+j]=i*m+j;
        }
    }
    int count = 0;
    for(int i = 0; i<n; ++i){
        for(int j=0;j<m;++j){
            if(grid[i][j]==1){
                if(i>0 && grid[i-1][j]==1){				
                    unionFather(father, i*m+j,(i-1)*m+j);
                }
                if(j>0 && grid[i][j-1] == 1){
                    unionFather(father,i*m+j,i*m+j-1);
                }
            }
        }
    }
    
    for(int i=0;i<n;++i){
        for(int j=0;j<m;++j){
            if(grid[i][j] == 1 &&father[i*m+j] ==i*m+j)
                ++count;
        }
    }
    delete[] father;
    return count;
}



int main(){	
	int n = 0, m = 0, count = 0;
    string str;
    int num;
    
	cin >> m; 
	cin >> n;
	getchar();
	
	int **data = new int*[m];
	for(int i=0; i<m; ++i){
		data[i] = new int[n];
	}
	
	
	for(int i=0; i<m; i++){
		getline(cin, str);
	    istringstream is(str);  
	    int j = 0;
	    while((is >> num) && (j < n))  
	    {  
			data[i][j] = num;
			++j; 	        
	    }    	    
	}  
	
	
       
    count = countHomes(data, n, m);//使用并查集
	cout << count << endl;
	
	return 0;
}

方法二:使用DSF

 #include <iostream>
 #include <sstream>
 #include <string>
 
 using namespace std;
 
 void dfs(int **grid, int** book, int n, int m, int x, int y, int color){
 	int tx, ty;
 	int next[4][2] = {{0,1},{1,0},{0,-1},{-1,0}};
 	
 	grid[x][y] = color;
 	for(int k=0; k<=3; k++){
 		tx = x + next[k][0];
		ty = y + next[k][1];
		
		//是否越界 
		if(tx<0 || tx >= n || ty < 0 || ty >= m){
			continue;
		}	
		
		//是否房屋 
		if(grid[tx][ty] > 0 && book[tx][ty] == 0){
			book[tx][ty] = 1;
			dfs(grid, book, n, m, tx, ty, color);
		}
	}
 	
 }
 
int countHomes(int **grid, int n, int m)  
{  
	int num = 0;
	
	int **book = new int*[m];  
    for(int i=0; i<m; i++){  
        book[i] = new int[n];  
    }  
    for(int i=0; i<m; i++)
    	for(int j=0; j<n; j++)
			book[i][j] = 0;
	
 
    for(int i=0; i<m; i++){
    	for(int j=0; j<n; j++){
    		if(grid[i][j] > 0){
    			num--;
    			book[i][j] = 1;
    			dfs(grid, book, n, m, i, j, num);
			}
		}
	}
    return -num;  
}  
 
 int main(){   
    int n = 0, m = 0, count = 0;  
    string str;  
    int num;  
      
    cin >> m;   
    cin >> n;  
    getchar();  
         
    int **data = new int*[m];  
    for(int i=0; i<m; ++i){  
        data[i] = new int[n];  
    }  
    
      
    //读入地图 
    for(int i=0; i<m; i++){  
        getline(cin, str);  
        istringstream is(str);    
        int j = 0;  
        while((is >> num) && (j < n))    
        {    
            data[i][j] = num;  
            ++j;              
        }             
    }    
         	
	count = countHomes(data, n, m);//使用dfs  
    cout << count <<endl;
    
      
    return 0;  
}  

输入:

10
10
1 2 1 0 0 0 0 0 2 3
3 0 2 0 1 2 1 0 1 2
4 0 1 0 1 2 3 2 0 1
3 2 0 0 0 1 2 4 0 0
0 0 0 0 0 0 1 5 3 0
0 1 2 1 0 1 5 4 3 0
0 1 2 3 1 3 6 2 1 0
0 0 3 4 8 9 7 5 0 0
0 0 0 3 7 8 6 0 1 2
0 0 0 0 0 0 0 0 1 0

输出:

4

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值