uva 1590 - IP Networks(IP地址)
習題4-5 IP網絡(IP Networks, ACM/ICPC NEERC 2005, UVa1590)
可以用一個網絡地址和一個子網掩碼描述一個子網(即連續的IP地址範圍)。其中子網
掩碼包含32個二進制位,前32-n位為1,後n位為0,網絡地址的前32-n位任意,後n位為0。
所有前32-n位和網絡地址相同的IP都屬於此網絡。
例如,網絡地址為194.85.160.176(二進制為11000010|01010101|10100000|10110000),
子網掩碼為255.255.255.248(二進制為11111111|11111111|11111111|11111000),則該子網
的IP地址範圍是194.85.160.176~194.85.160.183。輸入一些IP地址,求最小的網絡(即包含IP
地址最少的網絡),包含所有這些輸入地址。
例如,若輸入3個IP地址:194.85.160.177、194.85.160.183和194.85.160.178,包含上述3
個地址的最小網絡的網絡地址為194.85.160.176,子網掩碼為255.255.255.248。
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
【註意:他可能有很多組輸入,而每組輸出之間沒有空行】
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=833&problem=4465&mosmsg=Submission+received+with+ID+21184770
思路:
1、先將所有ip存起來,用數組或容器什麽的。
2、轉換二進制
3、從第一位開始,諸位比較所有的ip在這一位上的數字一樣否
4、判斷出最小網絡位數,即掩碼為1的位數。
5、轉換十進制
(我用來存二進制的ip用的是string)
(用了下vector,當然也可以用數組存,一個32*1000的數組)
/* 110000100101010110100000_10110001 110000100101010110100000_10110111 110000100101010110100000_10110010 11000010010101011010000010110000 11111111111111111111111111111000 */ //特殊情況:只輸入一個IP地址,這時掩碼應該32位1 #include<iostream> #include<stack> #include<string> #include<vector> #include<cmath> #include<cstdio> using namespace std; string binary(int dec) { string str="00000000"; stack<int> s; int bin=0; for(int i=7;i>=0;i--) { //s.push(dec%2); str[i]=dec%2+‘0‘; dec /= 2; } // while(!s.empty()) // { // bin = bin*10 + s.top(); // s.pop(); // } // return bin; return str; } int decimal(string bin) { int dec =0; for(int i=0;i<8;i++) //從高位開始 { dec += (int)pow(2,8-i-1)* (bin[i]-‘0‘); } return dec; } int main() { int T; while(cin>>T) { vector<string>ip; // 存儲輸入的所有ip int num=0; if(T==1) //防止只輸入一個地址的特殊情況 num=32; while(T--) //輸入 { int a[4]; string str; scanf("%d.%d.%d.%d",&a[0],&a[1],&a[2],&a[3]); for(int i=0;i<4;i++) { str += binary(a[i]); } ip.push_back(str); } for(int j=0;j<32;j++) //判斷相等的位數 { int iff=0; for(int i=1;i<ip.size();i++) { //cout<<ip.at(i)<<endl; if(ip.at(0)[j] == ip.at(i)[j]) //這一位相等 { iff=1; } else { iff=0; break; } } if(iff) //這一位相等,掩碼位數加一 num++; else break; } string zero="00000000"; //備用0 string mask,minip; int score[4];//存儲最小網絡的四個十進制ip地址段 int score2[4];//存儲mask的四個十進制的ip地址段 for(int i=1;i<=32-num;i++) //先從最後開始補0 { minip=‘0‘+minip; mask=‘0‘+mask; } for(int i=num-1;i>=0;i--) //倒的補 { minip=ip[0].at(i)+minip; mask=‘1‘+mask; } // cout<<num<<endl; // for(int i=0;i<ip.size();i++) // cout<<ip[i]<<endl; // cout<<endl; // cout<<mask<<endl; for(int i=0;i<4;i++) //運算最小網絡 { score[i] =decimal(minip.substr(i*8,8)); score2[i] =decimal(mask.substr(i*8,8)); //以下淘汰的方法是:邊變換,邊比對是否位數到了最小網絡位。 //比較上面的先做好一個最小網絡的二進制地址,然後在直接變換。要更復雜 // if(i*8+8>num) // { // //cout<<i*8<<" "<<num<<endl; // //cout<<ip[0].substr(i*8,num-i*8)<<"|"<<zero.substr(0,32-num)<<endl; // score[i]=decimal(ip[0].substr(i*8,num-i*8)+zero.substr(0,32-num)); // } // else // { // //cout<<ip[0].substr(i*8,8)<<endl; // score[i]=decimal(ip[0].substr(i*8,8)); // } } printf("%d.%d.%d.%d\n",score[0],score[1],score[2],score[3]); printf("%d.%d.%d.%d\n",score2[0],score2[1],score2[2],score2[3]); } return 0; } //AC at 2018/4/22
(題外話:好在上學期的網絡課設就是算ip地址,所以這道題我才想了半個多小時就有思路了(哭))
uva 1590 - IP Networks(IP地址)