《算法竞赛入门经典》 习题4-5 IP网络(IP Networks,ACM、ICPC NEERC 2005,UVa1590)
原題及翻譯
Alex is administrator of IP networks.
亞歷克斯是IP網(wǎng)絡(luò)的管理員。
His clients have a bunch of individual IP addresses and he decided to group all those IP addresses into the smallest possible IP network.
他的客戶機有一堆單獨的IP地址,他決定將所有這些IP地址分組到盡可能小的IP網(wǎng)絡(luò)中。
Each IP address is a 4-byte number that is written byte-by-byte in a decimal dot-separated notation “byte0.byte1.byte2.byte3” (quotes are added for clarity).
每個IP地址都是一個4字節(jié)的數(shù)字,它是以小數(shù)點分隔的符號“byte0.byte1.byte2.byte3”逐字節(jié)寫入的(為了清晰起見,添加了引號)。
Each byte is written as a decimal number from 0 to 255 (inclusive) without extra leading zeroes.
每個字節(jié)都寫為一個從0到255(包括0到255)的十進制數(shù)字,沒有額外的前導(dǎo)零。
IP network is described by two 4-byte numbers — network address and network mask.
IP網(wǎng)絡(luò)由兩個4字節(jié)的數(shù)字(網(wǎng)絡(luò)地址和網(wǎng)絡(luò)掩碼)描述。
Both network address and network mask are written in the same notation as IP addresses.
網(wǎng)絡(luò)地址和網(wǎng)絡(luò)掩碼都以與IP地址相同的符號寫入。
In order to understand the meaning of network address and network mask you have to consider their binary representation.
為了理解網(wǎng)絡(luò)地址和網(wǎng)絡(luò)掩碼的含義,必須考慮它們的二進制表示。
Binary representation of IP address, network address, and network mask consists of 32 bits:
IP地址、網(wǎng)絡(luò)地址和網(wǎng)絡(luò)掩碼的二進制表示由32位組成:
8 bits for byte0 (most significant to least significant), followed by 8 bits for byte1, followed by 8 bits for byte2, and followed by 8 bits for byte3.
8位代表字節(jié)0(最高有效到最低有效),8位代表字節(jié)1,8位代表字節(jié)2,8位代表字節(jié)3。
IP network contains a range of 2n IP addresses where 0 n 32.
IP網(wǎng)絡(luò)包含2N個IP地址范圍,其中0 N 32。
Network mask always has32 n first bits set to one, and n last bits set to zero in its binary representation.
網(wǎng)絡(luò)掩碼始終具有在二進制表示中,32個N的第一位設(shè)置為1,N的最后一位設(shè)置為0。
Network address has arbitrary 32 n first bits, and n last bits set to zero in its binary representation.
網(wǎng)絡(luò)地址在其二進制表示中有任意的32N個第一位和N個最后位設(shè)置為零。
IP network contains all IP addresses whose 32 n first bits are equal to 32 n first bits of network address with arbitrary n last bits.
IP網(wǎng)絡(luò)包含所有IP地址,其中32個n第一位等于網(wǎng)絡(luò)地址的32個n第一位,任意n個最后一位。
We say that one IP network is smaller than the other IP network if it contains fewer IP addresses.
如果它包含更少的IP地址,我們說一個IP網(wǎng)絡(luò)比另一個IP網(wǎng)絡(luò)小。
For example, IP network with network address 194.85.160.176 and network mask 255.255.255.248 contains 8 IP addresses from 194.85.160.176 to 194.85.160.183 (inclusive).
例如,網(wǎng)絡(luò)地址為194.85.160.176、網(wǎng)絡(luò)掩碼為255.255.255.248的IP網(wǎng)絡(luò)包含8個從194.85.160.176到194.85.160.183(含)的IP地址。
Input
輸入
The input file will contain several test cases, each of them as described below.
輸入文件將包含幾個測試用例,每個測試用例如下所述。
The first line of the input file contains a single integer number m (1 m 1000).
輸入文件的第一行包含一個整數(shù)m(1 m 1000)。
The following m lines contain IP addresses, one address on a line.
下面的M行包含IP地址,一行上有一個地址。
Each IP address may appear more than once in the input file.
每個IP地址可能在輸入文件中出現(xiàn)多次。
Output
輸出
For each test case, write to the output file two lines that describe the smallest possible IP network that contains all IP addresses from the input file.
對于每個測試用例,向輸出文件寫入兩行,描述包含輸入文件中所有IP地址的最小可能IP網(wǎng)絡(luò)。
Write network address on the first line and network mask on the second line.
在第一行寫網(wǎng)絡(luò)地址,在第二行寫網(wǎng)絡(luò)掩碼。
Sample Input
3
194.85.160.177
194.85.160.183
194.85.160.178
Sample Output
194.85.160.176
255.255.255.248
題目理解
可以用一個網(wǎng)絡(luò)地址和一個子網(wǎng)掩碼描述一個子網(wǎng)(即連續(xù)的IP地址范圍)。其中子網(wǎng)掩碼包含32個二進制位,前32-n位為1,后n位為0,網(wǎng)絡(luò)地址的前32-n位任意,后n位為0。所有前32-n位和網(wǎng)絡(luò)地址相同的IP都屬于此網(wǎng)絡(luò)。
例如,網(wǎng)絡(luò)地址為194.85.160.176
(二進制為11000010|01010101|10100000|1011000),
子網(wǎng)掩碼為255.255.255.248
(二進制為11111111|11111111|11111111|11111000),
則該子網(wǎng)的IP地址范圍是194.85.160.176~194.85.160.183。
輸入一些IP地址,求最小的網(wǎng)絡(luò)(即包含IP地址最少的網(wǎng)絡(luò)),包含所有這些輸入地址。
思路
這道題有兩種解法(至少我就只寫兩種):
第一種需要一點計算機網(wǎng)絡(luò)方面的基礎(chǔ)知識,知道IP地址、網(wǎng)絡(luò)地址、子網(wǎng)掩碼之間的關(guān)系和計算步驟。利用IP差計算子網(wǎng)數(shù),然后根據(jù)二進制子網(wǎng)數(shù)的位數(shù)和IP地址的類別寫出子網(wǎng)掩碼,最后再轉(zhuǎn)換網(wǎng)絡(luò)地址。
第二種方法比較簡單,利用給出的IP地址的計算出子網(wǎng)的最大和最小IP,然后進行轉(zhuǎn)換,最小IP轉(zhuǎn)換成網(wǎng)絡(luò)地址,最大IP轉(zhuǎn)換為子網(wǎng)掩碼。(這也是我看到一位小哥的思路之后發(fā)現(xiàn)很好,才寫上的)
代碼分析
1.首先,因為題目涉及到二進制與十進制之間的轉(zhuǎn)換,所以先寫兩個轉(zhuǎn)換函數(shù):
十進制數(shù)轉(zhuǎn)換為二進制數(shù)
二進制數(shù)轉(zhuǎn)換為十進制數(shù)
void binary_number_to_decimal_number(IP_address &x) {memset(x.dotted_decimal_format,0,sizeof(x.dotted_decimal_format));for(int i=0;i<4;i++){for(int j=0;j<8;j++){x.dotted_decimal_format[i]*=2;x.dotted_decimal_format[i]+=x.Binary_format[i][j];}} }2.根據(jù)第二種方法,程序還需要一個比較函數(shù),來決定最大值和最小值:
bool bigger(IP_address x,IP_address y) {for(int i=0;i<4;i++){if(x.dotted_decimal_format[i]>y.dotted_decimal_format[i]) return true;else if(x.dotted_decimal_format[i]<y.dotted_decimal_format[i]) return false;}return false; } bool smller(IP_address x,IP_address y) {for(int i=0;i<4;i++){if(x.dotted_decimal_format[i]<y.dotted_decimal_format[i]) return true;else if(x.dotted_decimal_format[i]>y.dotted_decimal_format[i]) return false;}return false; }3.最后寫main()函數(shù),用于讀入和處理數(shù)據(jù)以及調(diào)用一些函數(shù):
int main() {int n;IP_address ip,ip_max,ip_min;while(scanf("%d",&n)!=EOF){for(int i=0;i<n;i++){for(int j=0;j<4;j++){scanf("%d%*c",&ip.dotted_decimal_format[j]);}if(i==0){ip_max=ip;ip_min=ip;}else{if(bigger(ip,ip_max)){ip_max=ip;}if(smller(ip,ip_min)){ip_min=ip;}}}decimal_number_to_binary_number(ip_min);decimal_number_to_binary_number(ip_max);check(ip_min,ip_max);binary_number_to_decimal_number(ip_min);binary_number_to_decimal_number(ip_max);printf("%d.%d.%d.%d\n",ip_min.dotted_decimal_format[0],ip_min.dotted_decimal_format[1],ip_min.dotted_decimal_format[2],ip_min.dotted_decimal_format[3]);printf("%d.%d.%d.%d\n",ip_max.dotted_decimal_format[0],ip_max.dotted_decimal_format[1],ip_max.dotted_decimal_format[2],ip_max.dotted_decimal_format[3]);}return 0; }完整代碼
#include <cstdio> #include <iostream> #include <cctype> #include <cmath> #include <cstring> using namespace std; struct IP_address {int dotted_decimal_format[4];char Binary_format[4][8]; }; bool bigger(IP_address x,IP_address y) {for(int i=0;i<4;i++){if(x.dotted_decimal_format[i]>y.dotted_decimal_format[i]) return true;else if(x.dotted_decimal_format[i]<y.dotted_decimal_format[i]) return false;}return false; } bool smller(IP_address x,IP_address y) {for(int i=0;i<4;i++){if(x.dotted_decimal_format[i]<y.dotted_decimal_format[i]) return true;else if(x.dotted_decimal_format[i]>y.dotted_decimal_format[i]) return false;}return false; } void decimal_number_to_binary_number(IP_address &x) {int temp;memset(x.Binary_format,0, sizeof(x.Binary_format));for(int i=0;i<4;i++){temp=x.dotted_decimal_format[i];for(int j=7;j>=0;j--){if(temp==0) break;x.Binary_format[i][j]=temp%2;temp/=2;}} } void binary_number_to_decimal_number(IP_address &x) {memset(x.dotted_decimal_format,0,sizeof(x.dotted_decimal_format));for(int i=0;i<4;i++){for(int j=0;j<8;j++){x.dotted_decimal_format[i]*=2;x.dotted_decimal_format[i]+=x.Binary_format[i][j];}} } void check(IP_address &min, IP_address &max) {bool t=false;for(int i=0;i<4;i++){for(int j=0;j<8;j++){if(t){min.Binary_format[i][j]=0;max.Binary_format[i][j]=0;}else{if(min.Binary_format[i][j]!=max.Binary_format[i][j]){t = true;min.Binary_format[i][j]=0;max.Binary_format[i][j]=0;}else{max.Binary_format[i][j]=1;}}}} } int main() {int n;IP_address ip,ip_max,ip_min;while(scanf("%d",&n)!=EOF){for(int i=0;i<n;i++){for(int j=0;j<4;j++){scanf("%d%*c",&ip.dotted_decimal_format[j]);}if(i==0){ip_max=ip;ip_min=ip;}else{if(bigger(ip,ip_max)){ip_max=ip;}if(smller(ip,ip_min)){ip_min=ip;}}}decimal_number_to_binary_number(ip_min);decimal_number_to_binary_number(ip_max);check(ip_min,ip_max);binary_number_to_decimal_number(ip_min);binary_number_to_decimal_number(ip_max);printf("%d.%d.%d.%d\n",ip_min.dotted_decimal_format[0],ip_min.dotted_decimal_format[1],ip_min.dotted_decimal_format[2],ip_min.dotted_decimal_format[3]);printf("%d.%d.%d.%d\n",ip_max.dotted_decimal_format[0],ip_max.dotted_decimal_format[1],ip_max.dotted_decimal_format[2],ip_max.dotted_decimal_format[3]);}return 0; }每天磕一道ACM打卡
總結(jié)
以上是生活随笔為你收集整理的《算法竞赛入门经典》 习题4-5 IP网络(IP Networks,ACM、ICPC NEERC 2005,UVa1590)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 百练1724:ROADS
- 下一篇: 基础练习 数列特征