逐个考虑所有情况,并且逐一检验。
枚举的时候应该注意
- 建立简介的数学模型,尽量减少变量
- 减少搜索空间,在做算法题的时候防止超时,一般是109数量级容易超时,所以缩小各个变量的取值范围
- 采用合适的搜索数据,看从大到小还是从小到
假币问题(POJ2692)
解题思路:枚举12枚硬币是真币和假币的情况,一共24种
一共两种做法,第二种算法跟着老师敲得,但是一直都是wrong,第一种算法是跟着书上敲得是真正确的,这道题以及做的好多遍了,每次都好像会卡主,希望下次可以做出来!
#include <iostream>
using namespace std;
char left_[3][7],right_[3][7],result[3][7];
int st[12];
bool balanced()
{
int leftw=0,rightw=0;
for(int i=0;i<3;i++)
{
leftw=0;
rightw=0;
int k;
for( k=0;k<6&&left_[i][k]!=0;k++)
{
leftw+=st[left_[i][k]-'A'];
rightw+=st[right_[i][k]-'A'];
}
if(leftw>rightw&&result[i][0]!='u') return false;
if(leftw==rightw&&result[i][0]!='e') return false;
if(leftw<rightw&&result[i][0]!='d') return false;
}
return true;
}
int main()
{
int n;
cin>>n;
while(n--)
{
for(int i=0;i<12;i++) st[i]=0;
for(int i=0;i<3;i++)
{
cin>>left_[i]>>right_[i]>>result[i];
}
int i=0;
for(i=0;i<12;i++)
{
st[i]=1;
if(balanced())
{
break;
}
st[i]=-1;
if(balanced())
{
break;
}
st[i]=0;
}
printf("%c is the counterfeit coin and it is %s.\n",i+'A',st[i]>0?"heavy":"light");
}
}
#include <iostream>
#include <cstring>
using namespace std;
char Left[5][10],Right[5][10],result[5][10];
int n;
bool isFake(char c,bool light){//假设C是假币,light为真表示假币是比较轻的
for(int i=0;i<3;i++){
char *pLeft,*pright;//指针? 对于指针的用法不是掌握的很熟练
if(light){//如果假币是比较轻,pleft指向左边
pLeft=Left[i];
pright=Right[i];
}
else{//注意 指针的指向的变化
pLeft=Right[i];
pright=Left[i];
}
switch(result[i][0]){//switch函数的用法
case'u':
if(strchr(pright,c)== NULL)//strchr 的用法 如果结果是up,但是c没有在右边,则就返回false ,注意NULL要大写,不然会找不到
return false;// char *strchr(const char *str, int c) 在参数 str 所指向的字符串中搜索第一次出现字符 c(一个无符号字符)的位置
break;
case'e':
if(strchr(pLeft,c)||strchr(pright,c))
return false;
break;
case'd':
if(strchr(pLeft,c)==NULL)
return false;
break;
}
}
return true;
}
int main(){
cin>>n;
while(n--){
for(int i=0;i<3;i++){
cin>>Left[i]>>Right[i]>>result[i];//这个地方最开始没有想出来,对字符的输入没有掌握清楚
}
for(char c='A';c<='L';c++ ){//枚举A-L是否为假币
if(isFake(c,true)){
cout<<c<<" is the counterfeit coin and it is light.\n ";
break;
}
else if(isFake(c,false)){//最开始在这个地方出现bug,没有添加条件判断,导致最后结果出错
cout<<c<<" is the counterfeit coin and it is heavy.\n ";
break;
}
}
return 0;
} }
想:这道题,主要是自己对枚举的感觉没有出来,不知道该怎么枚举,希望下次见到这种类似的题,可以有点感觉!
生理周期(POJ4148)
解题思路:从给定的时间开始,遍历到结束的时间。对于每一个K都要看是否满足三个高峰期的时间 。这里就可以通过跳着试来提高算法的速度。
#include <iostream>
using namespace std;
int k;
int main(){
int p,e,i,d,caseNo;
while(cin>>p>>e>>i>>d&&p!=-1){
caseNo++;
int k;
for(k=d+1;(k-p)%23;k++);//这里跳着试
for(;(k-e)%28;k+=23);
for(;(k-i)%33;k+=23*28);
cout<<"Case "<<caseNo<<": the next triple peak occurs in "<<k-d<<" days."<<endl;
}
return 0;
}
想:这道题感觉挺简单的,但是自己就是好像没有理清各个变量的关系,导致自己也没有做出来,觉得思绪很乱,其实理清各个变量之间的关系,还是挺简单的,希望下次在做这个题可以好好想想。