枚举 记录ing

逐个考虑所有情况,并且逐一检验。

枚举的时候应该注意

  1. 建立简介的数学模型,尽量减少变量
  2. 减少搜索空间,在做算法题的时候防止超时,一般是109数量级容易超时,所以缩小各个变量的取值范围
  3. 采用合适的搜索数据,看从大到小还是从小到

 假币问题(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;
}

想:这道题感觉挺简单的,但是自己就是好像没有理清各个变量的关系,导致自己也没有做出来,觉得思绪很乱,其实理清各个变量之间的关系,还是挺简单的,希望下次在做这个题可以好好想想。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值