纠结一个下午,发现自己真的是越来越菜了,以前做的很快的题竟然久战不下!以后得在poj上常练了!
以下是源码,比较乱,难得整理了……回溯法的应用
#include
<
iostream
>
#include < fstream >
using namespace std;
const int MAX = 1000 ;
int typeValue[MAX];
int x[MAX]; // 每种对应的张数,回溯时用
int xx[MAX];
int Request[MAX];
int maxKind = 0 ;
int totalStemps = 100000 ;
int maxValue = 0 ;
bool isTie = false ;
int CurrentKind = 0 ;
int CurrentTotalStamps = 0 ;
int CurrentMaxValue = 0 ;
int typeNum = 0 ;
int requestNum = 0 ;
int CurrentRequest = 0 ;
void f( int n, int currentSum, int * x);
// 在当前和为currentSum,剩余最大和为leftsum的前提下,第n
// 种面值邮票的选择情况,选择张数结果存放在x[n-1]中
int main()
{
ifstream cin( " in.txt " );
ofstream cout( " out.txt " );
int temp = 0 ;
while (cin >> temp)
{
typeNum = 0 ;
requestNum = 0 ;
if (temp != 0 )
{
typeValue[typeNum ++ ] = temp;
}
while ((cin >> temp,temp) != 0 )
{
typeValue[typeNum ++ ] = temp;
}
while ((cin >> temp,temp) != 0 )
{
Request[requestNum ++ ] = temp;
}
for ( int t = 0 ;t < requestNum;t ++ )
{
maxKind = 0 ;
totalStemps = 100000 ;
maxValue = 0 ;
isTie = false ;
memset(x, 0 ,MAX * sizeof ( int ));
memset(xx, 0 ,MAX * sizeof ( int ));
int currentSum = 0 ;
CurrentRequest = Request[t];
CurrentKind = 0 ;
CurrentTotalStamps = 0 ;
CurrentMaxValue = 0 ;
f( 0 ,currentSum,x);
if (maxKind == 0 )
{
cout << Request[t] << " ---- none " ;
}
else
{
if (isTie)
{
cout << Request[t] << " ( " << maxKind << " ): tie " ;
}
else
{
cout << Request[t] << " ( " << maxKind << " ): " ;
for ( int k = 0 ;k < typeNum;k ++ )
{
if (xx[k] > 0 )
{
for ( int count = 0 ;count < xx[k];count ++ )
{
if (count == xx[k] - 1 )
{
cout << typeValue[k];
}
else
{
cout << typeValue[k] << " " ;
}
}
if (k != typeNum - 1 )
{
cout << " " ;
}
}
}
}
}
cout << " \n " ;
}
}
return 0 ;
}
void f( int n, int currentSum, int * x)
{
int m = 0 ;
if (n >= typeNum)
{
if (currentSum == CurrentRequest)
{
if (CurrentKind > maxKind)
{
maxKind = CurrentKind;
totalStemps = CurrentTotalStamps;
maxValue = CurrentMaxValue;
isTie = false ;
for ( m = 0 ;m < typeNum;m ++ )
{
xx[m] = x[m];
}
}
else if (CurrentKind == maxKind)
{
if (CurrentTotalStamps < totalStemps)
{
totalStemps = CurrentTotalStamps;
maxValue = CurrentMaxValue;
isTie = false ;
for ( m = 0 ;m < typeNum;m ++ )
{
xx[m] = x[m];
}
}
else if (CurrentTotalStamps == totalStemps)
{
if (CurrentMaxValue > maxValue)
{
maxValue = CurrentMaxValue;
for ( m = 0 ;m < typeNum;m ++ )
{
xx[m] = x[m];
}
isTie = false ;
}
else if (CurrentMaxValue == maxValue)
{
isTie = true ;
}
}
}
}
return ;
}
else
{
for (x[n] = 0 ;x[n] <= ( 4 - CurrentTotalStamps);x[n] ++ )
{
int temp1 = CurrentMaxValue;
if ((currentSum + x[n] * typeValue[n]) <= CurrentRequest)
{
if ( x[n] != 0 )
CurrentKind ++ ;
if (x[n] != 0 && typeValue[n] > CurrentMaxValue) // 必须加上x[n]!=0 ,因为对于4=3+1+0
// (某种票不选的情况)和(3,1)相比,不能更新最大值,因为没有选则,但搜索时会出现这种情况
{
CurrentMaxValue = typeValue[n];
}
CurrentTotalStamps += x[n];
f(n + 1 ,currentSum + x[n] * typeValue[n],x);
if ( x[n] != 0 )
CurrentKind -- ;
CurrentMaxValue = temp1;
CurrentTotalStamps -= x[n];
}
}
}
}
#include < fstream >
using namespace std;
const int MAX = 1000 ;
int typeValue[MAX];
int x[MAX]; // 每种对应的张数,回溯时用
int xx[MAX];
int Request[MAX];
int maxKind = 0 ;
int totalStemps = 100000 ;
int maxValue = 0 ;
bool isTie = false ;
int CurrentKind = 0 ;
int CurrentTotalStamps = 0 ;
int CurrentMaxValue = 0 ;
int typeNum = 0 ;
int requestNum = 0 ;
int CurrentRequest = 0 ;
void f( int n, int currentSum, int * x);
// 在当前和为currentSum,剩余最大和为leftsum的前提下,第n
// 种面值邮票的选择情况,选择张数结果存放在x[n-1]中
int main()
{
ifstream cin( " in.txt " );
ofstream cout( " out.txt " );
int temp = 0 ;
while (cin >> temp)
{
typeNum = 0 ;
requestNum = 0 ;
if (temp != 0 )
{
typeValue[typeNum ++ ] = temp;
}
while ((cin >> temp,temp) != 0 )
{
typeValue[typeNum ++ ] = temp;
}
while ((cin >> temp,temp) != 0 )
{
Request[requestNum ++ ] = temp;
}
for ( int t = 0 ;t < requestNum;t ++ )
{
maxKind = 0 ;
totalStemps = 100000 ;
maxValue = 0 ;
isTie = false ;
memset(x, 0 ,MAX * sizeof ( int ));
memset(xx, 0 ,MAX * sizeof ( int ));
int currentSum = 0 ;
CurrentRequest = Request[t];
CurrentKind = 0 ;
CurrentTotalStamps = 0 ;
CurrentMaxValue = 0 ;
f( 0 ,currentSum,x);
if (maxKind == 0 )
{
cout << Request[t] << " ---- none " ;
}
else
{
if (isTie)
{
cout << Request[t] << " ( " << maxKind << " ): tie " ;
}
else
{
cout << Request[t] << " ( " << maxKind << " ): " ;
for ( int k = 0 ;k < typeNum;k ++ )
{
if (xx[k] > 0 )
{
for ( int count = 0 ;count < xx[k];count ++ )
{
if (count == xx[k] - 1 )
{
cout << typeValue[k];
}
else
{
cout << typeValue[k] << " " ;
}
}
if (k != typeNum - 1 )
{
cout << " " ;
}
}
}
}
}
cout << " \n " ;
}
}
return 0 ;
}
void f( int n, int currentSum, int * x)
{
int m = 0 ;
if (n >= typeNum)
{
if (currentSum == CurrentRequest)
{
if (CurrentKind > maxKind)
{
maxKind = CurrentKind;
totalStemps = CurrentTotalStamps;
maxValue = CurrentMaxValue;
isTie = false ;
for ( m = 0 ;m < typeNum;m ++ )
{
xx[m] = x[m];
}
}
else if (CurrentKind == maxKind)
{
if (CurrentTotalStamps < totalStemps)
{
totalStemps = CurrentTotalStamps;
maxValue = CurrentMaxValue;
isTie = false ;
for ( m = 0 ;m < typeNum;m ++ )
{
xx[m] = x[m];
}
}
else if (CurrentTotalStamps == totalStemps)
{
if (CurrentMaxValue > maxValue)
{
maxValue = CurrentMaxValue;
for ( m = 0 ;m < typeNum;m ++ )
{
xx[m] = x[m];
}
isTie = false ;
}
else if (CurrentMaxValue == maxValue)
{
isTie = true ;
}
}
}
}
return ;
}
else
{
for (x[n] = 0 ;x[n] <= ( 4 - CurrentTotalStamps);x[n] ++ )
{
int temp1 = CurrentMaxValue;
if ((currentSum + x[n] * typeValue[n]) <= CurrentRequest)
{
if ( x[n] != 0 )
CurrentKind ++ ;
if (x[n] != 0 && typeValue[n] > CurrentMaxValue) // 必须加上x[n]!=0 ,因为对于4=3+1+0
// (某种票不选的情况)和(3,1)相比,不能更新最大值,因为没有选则,但搜索时会出现这种情况
{
CurrentMaxValue = typeValue[n];
}
CurrentTotalStamps += x[n];
f(n + 1 ,currentSum + x[n] * typeValue[n],x);
if ( x[n] != 0 )
CurrentKind -- ;
CurrentMaxValue = temp1;
CurrentTotalStamps -= x[n];
}
}
}
}