考察点:枚举法
传送门:http://poj.org/problem?id=1543
POJ1543 完美立方
题目描述:
Description
For hundreds of years Fermat's Last Theorem, which stated simply that for n > 2 there exist no integers a, b, c > 1 such that a^n = b^n + c^n, has remained elusively unproven. (A recent proof is believed to be correct, though it is still undergoing scrutiny.) It is possible, however, to find integers greater than 1 that satisfy the "perfect cube" equation a^3 = b^3 + c^3 + d^3 (e.g. a quick calculation will show that the equation 12^3 = 6^3 + 8^3 + 10^3 is indeed true). This problem requires that you write a program to find all sets of numbers {a,b,c,d} which satisfy this equation for a <= N.
Input
One integer N (N <= 100).
Output
The output should be listed as shown below, one perfect cube per line, in non-decreasing order of a (i.e. the lines should be sorted by their a values). The values of b, c, and d should also be listed in non-decreasing order on the line itself. There do exist several values of a which can be produced from multiple distinct sets of b, c, and d triples. In these cases, the triples with the smaller b values should be listed first.
思想:只需要把4个参数中的所有值都扫描一遍,看是否符合要求。
Source Code:
//寻找完美立方等式
#include <iostream>
using namespace std;
int main()
{
int n;
cin >> n;
int a, b, c, d;
int three[101];
for( int i = 0; i < 101; i++ )
three[ i ] = i * i *i;
int result;
for( a = 3; a <= n; a++)
for( b = 2; b <=n; b++ )
for( c = 2; c <= n; c++ )
for( d =2; d <= n; d++ )
{
result = ( three[ b ] + three[ c ] + three[ d ] ) ;
if( three[ a ] == result )
cout << "Cube = " << a << ",Triple = (" << b << "," << c << "," << d <<")" << endl;
}
}
结果:
题目要求输出的时候,b,c,d按照非降序排列输出,则b < c < d,修改代码,提交,AC通过。代码如下:
//寻找完美立方等式
#include <iostream>
using namespace std;
int main()
{
int n;
cin >> n;
int a, b, c, d;
int three[101];
for( int i = 0; i < 101; i++ )
three[ i ] = i * i *i;
int result;
for( a = 3; a <= n; a++)
for( b = 2; b <=n; b++ )
for( c = b; c <= n; c++ )
for( d =c; d <= n; d++ )
{
result = ( three[ b ] + three[ c ] + three[ d ] ) ;
if( three[ a ] == result )
cout << "Cube = " << a << ", Triple = (" << b << "," << c << "," << d <<")" << endl;
}
}
当然,这样搜索的范围仍然太多,时间复杂度还是太大,我们需要做优化。
可以根据已知的东西来推出几个能够缩小范围的条件:
1.a一定大于b,c,d,所以bcd的for循环。只需要小于a就可以了,
2.在4层循环的第二层设立条件,如果
three[a] < three[b] * 3;
则没有必要继续向下循环了,因为c,和d向下循环的话只会越来越大。继续修改代码"
//寻找完美立方等式
#include <iostream>
using namespace std;
int main()
{
int n;
cin >> n;
int a, b, c, d;
int three[101];
for( int i = 0; i < 101; i++ )
three[ i ] = i * i *i;
int result;
for( a = 3; a <= n; a++)
{
for( b = 2; b <a; b++ )
{
if( three[ a ] < three[ b ] * 3)
break;
for( c = b; c < a; c++ )
for( d =c; d < a; d++ )
{
result = ( three[ b ] + three[ c ] + three[ d ] ) ;
if( three[ a ] == result )
cout << "Cube = " << a << ", Triple = (" << b << "," << c << "," << d <<")" << endl;
}
}
}
}
POJ1013 硬币问题:
传送门:http://poj.org/problem?id=1013
题目:
Description
Sally Jones has a dozen Voyageur silver dollars. However, only eleven of the coins are true silver dollars; one coin is counterfeit even though its color and size make it indistinguishable from the real silver dollars. The counterfeit coin has a different weight from the other coins but Sally does not know if it is heavier or lighter than the real coins.
Happily, Sally has a friend who loans her a very accurate balance scale. The friend will permit Sally three weighings to find the counterfeit coin. For instance, if Sally weighs two coins against each other and the scales balance then she knows these two coins are true. Now if Sally weighs
one of the true coins against a third coin and the scales do not balance then Sally knows the third coin is counterfeit and she can tell whether it is light or heavy depending on whether the balance on which it is placed goes up or down, respectively.
By choosing her weighings carefully, Sally is able to ensure that she will find the counterfeit coin with exactly three weighings.
Input
The first line of input is an integer n (n > 0) specifying the number of cases to follow. Each case consists of three lines of input, one for each weighing. Sally has identified each of the coins with the letters A--L. Information on a weighing will be given by two strings of letters and then one of the words ``up'', ``down'', or ``even''. The first string of letters will represent the coins on the left balance; the second string, the coins on the right balance. (Sally will always place the same number of coins on the right balance as on the left balance.) The word in the third position will tell whether the right side of the balance goes up, down, or remains even.
Output
For each case, the output will identify the counterfeit coin by its letter and tell whether it is heavy or light. The solution will always be uniquely determined.
Sample Input
1
ABCD EFGH even
ABCI EFJK up
ABIJ EFGH even
Sample Output
K is the counterfeit coin and it is light.
思想:
总共12个钱币,每个钱币要么是真币,要么是假币,假币要么比真币轻,要么比真币重。可以挨着对所有的去情形就行判断。
这里需要注意的一点是 右边高代表右边轻。。。在这点上卡了好久。。晕。审题不清楚。
代码:
#include <iostream>
#include <string.h>
using namespace std;
char leftInput[3][7],rightInput[3][7],result[3][5];//分别代表左边的3个输入,右边的3个,和3个结果
int main()
{
bool IsHeavy( char );//判断钱币是否为重
bool IsLight( char );//判断钱币是否为轻
int n;//
char c;//记录钱币的字母
cin >> n;
while( n )
{
cin.clear();
for(int i = 0; i < 3; i++ )
cin >> leftInput[i] >> rightInput[i] >> result[i] ;
for( c = 'A'; c <= 'L'; c++ )//搜索空间,每个位置存在两种情况
{
if( IsHeavy( c ) )
{
cout << c << " is the counterfeit coin and it is heavy." << endl;
break;
}
if( IsLight( c ) )
{
cout << c << " is the counterfeit coin and it is light." << endl;
break;
}
}
n--;
}
}
bool IsHeavy(char c)
{
for( int i = 0; i < 3; i++ )
{
switch( result[ i ][ 0 ])
{
//两边重量相等的情况,如果leftInput 和 rightInput中包含字符c,则肯定是真币,返回false
case 'e': if( strchr( leftInput[ i ], c ) != NULL || strchr( rightInput[ i ],c ) != NULL )//如果leftInput和rightInput中存在c,则肯定不是假币
return false;
break;
//右边轻的情况下,如果c是假币,且比真币重,则右边肯定包含假币,否则肯定会比左边轻,或者相等
case 'u': if( strchr( leftInput[ i ], c ) == NULL )
return false;//如果不包含c ,则返回false
break;
//右边重的情况下,如果c是假币,且比真币重,则左边肯定包含假币,否则肯定会比右边轻,或者相等
case 'd': if( strchr( rightInput[ i ], c ) == NULL )
return false;
break;
}
}
return true;
}
bool IsLight(char c)
{
for( int i = 0; i < 3; i++ )
{
switch( result[ i ][ 0 ] )
{
//两边重量相等的情况,如oleftInput 和 rightInput中包含字符c,则肯定是真币,
case 'e': if( strchr( leftInput[ i ], c ) != NULL || strchr( rightInput[ i ], c ) != NULL )//如果leftInput和rightInput中存在c,则肯定不是假币
return false;
break;
//右边清的情况下,如果c是假币,且比真币轻,则左边肯定包含假币,否则肯定会比左边重,或者相等
case 'u': if( strchr( rightInput[ i ], c ) == NULL )
return false;//如果不包含c ,则返回false
break;
//右边重的情况下,如果c是假币,且比真币重,则右边肯定包含假币,否则肯定会比右边轻,或者相等
case 'd': if( strchr( leftInput[ i ], c ) == NULL )
return false;
break;
}
}
return true;
}
用字符串来处理:
#include <iostream>
#include <string>
using namespace std;
string leftInput[ 3 ] ,rightInput[ 3 ], result[ 3 ];//分别代表左边的3个输入,右边的3个,和3个结果
int main()
{
bool IsHeavy( char );//判断钱币是否为重
bool IsLight( char );//判断钱币是否为轻
int n;//
char c;//记录钱币的字母
cin >> n;
while( n )
{
cin.clear();
for(int i = 0; i < 3; i++ )
cin >> leftInput[i] >> rightInput[i] >> result[i] ;
for( c = 'A'; c <= 'L'; c++ )//搜索空间,每个位置存在两种情况
{
if( IsHeavy( c ) )
{
cout << c << " is the counterfeit coin and it is heavy." << endl;
break;
}
if( IsLight( c ) )
{
cout << c << " is the counterfeit coin and it is light." << endl;
break;
}
}
n--;
}
}
bool IsHeavy(char c)
{
for( int i = 0; i < 3; i++ )
{
switch( result[ i ][ 0 ])
{
//两边重量相等的情况,如果leftInput 和 rightInput中包含字符c,则肯定是真币,返回false
case 'e': if( leftInput[ i ].find( c, 0 ) != -1 || rightInput[ i ].find( c, 0 ) != -1 )//如果leftInput和rightInput中存在c,则肯定不是假币
return false;
break;
//右边轻的情况下,如果c是假币,且比真币重,则右边肯定包含假币,否则肯定会比左边轻,或者相等
case 'u': if( leftInput[ i ].find( c, 0 ) == -1 )
return false;//如果不包含c ,则返回false
break;
//右边重的情况下,如果c是假币,且比真币重,则左边肯定包含假币,否则肯定会比右边轻,或者相等
case 'd': if( rightInput[ i ].find( c, 0 ) == -1 )
return false;
break;
}
}
return true;
}
bool IsLight(char c)
{
for( int i = 0; i < 3; i++ )
{
switch( result[ i ][ 0 ] )
{
//两边重量相等的情况,如oleftInput 和 rightInput中包含字符c,则肯定是真币,
case 'e': if( leftInput[ i ].find( c, 0 ) != -1 || rightInput[ i ].find( c, 0 ) != -1 )//如果leftInput和rightInput中存在c,则肯定不是假币
return false;
break;
//右边清的情况下,如果c是假币,且比真币轻,则左边肯定包含假币,否则肯定会比左边重,或者相等
case 'u': if( rightInput[ i ].find( c, 0 ) == -1 )
return false;//如果不包含c ,则返回false
break;
//右边重的情况下,如果c是假币,且比真币重,则右边肯定包含假币,否则肯定会比右边轻,或者相等
case 'd': if( leftInput[ i ].find( c, 0 ) == -1 )
return false;
break;
}
}
return true;
}