PKU 程序设计与算法(二)算法基础 Chapter 1.枚举 完美立方//POJ 1543 生理周期//POJ 1006 称硬币//POJ 1013

完美立方

Perfect Cubes

#include <iostream>
#include <cstdio>//C++最好用这个而不是stdio.h
using namespace std;
int main(int argc, char const *argv[])
{
	int n;
	cin>>n;
	for(int a=2;a<=n;++a)
		for(int b=2;b<a;++b)//因为答案要求b小的在前
			for(int c=b;c<a;++c)//因为b<=c<=d,**所以c从b开始向上找**
				for(int d=c;d<a;++d)//++i比i++效率高,这里又不需要返回值
					if(a*a*a==b*b*b+c*c*c+d*d*d)//简单的乘方不需要单独写一个了,效率更高
						printf("Cube=%d,Triple=(%d,%d,%d)\n",a,b,c,d);
	return 0;
}

生理周期

Biorhythms

#include <iostream>
#include <cstdio>
#define N 21252//上限,但是没什么用 
enum {P_PERIOD=23,E_PERIOD=28,I_PERIOD=33};
using namespace std;
int main(int argc, char const *argv[])
{
	int p,e,i,d,caseNo=0;
	//p->physical,e->emotional,i->intelligent 分别指各种指标的起始日期
	//d->day表示开始计数的第一天
	//CaseNo用来计数多组测试数据
	while(cin>>p>>e>>i>>d&&p!=-1)
	/*cin其实只是一个ostream类型的对象,作为了>>的左值(>>是二元运算符,左结合),对象哪来的返回值
	>>运算符会返回ostream对象,所以不能像scanf那样用int变量来接收cin的返回值
	但是cin的返回值可以被bool变量接收,表示输入流是否正常,接收到就返回true*/
	{ 
	if(p==0||e==0||i==0)
		{cout<<"Case "<<++caseNo<<":the next triple peak occurs in "<<N<<" days."<<endl;continue;}
	//异常数据处理,参考测试用例
	int k;
	for(k=d+1;(k-p)%P_PERIOD;++k);
	//这是一个单独的for,用来把k调到符合p的第一天,条件中只有当整除时为0不满足跳出,有余数的都会继续
	//在第一个能整除的位置停下,即到了满足p的第一天
	for(;(k-e)%E_PERIOD;k+=P_PERIOD);
	//同样是单独的for,继续找e的第一天,同时保持符合p
	//找出同时符合p,e的第一天
	for(;(k-i)%I_PERIOD;k+=P_PERIOD*E_PERIOD);//单独的for要打分号!不然把下面那句话也吃进去了 
	//找出符合p,e,i的第一天,完成任务
	cout<<"Case "<<++caseNo<<":the next triple peak occurs in "<<k-d<<" days."<<endl;
	//输出的是间隔 
	}
	return 0;
}

称硬币

Counterfeit Dollar

#include <iostream>
using namespace std;

enum{LIGHT,HEAVY};
bool isFake(char coin,bool state);//假设假的硬币的字母是coin,state表示是假设是轻的还是重的 
bool isInvolved(char ch,char* str);//检查字符是否包含在字符串中,可以用strchr代替
char left_coin[3][5],right_coin[3][5],result[3][5];//全局数组,方便沟通

int main(int argc, char const *argv[])
{
	int t;cin>>t;
	while(t--)//多组数据的处理
	{
		for(int i=0;i<3;++i)
			cin>>left_coin[i]>>right_coin[i]>>result[i];
		//读入测试数据,用空格分隔的数据用cin或者scanf读入 
		for(char ch='A';ch<='L';++ch)//从A到L遍历
		{
			if(isFake(ch,LIGHT))
			{
				cout<<ch<<" is the counterfeit coin and it is light."<<endl;
				break;
			}
			if(isFake(ch,HEAVY))
			{
				cout<<ch<<" is the counterfeit coin and it is heavy."<<endl;
				break;
			}
		}
	}
	return 0;
}

bool isFake(char coin,bool state)
//题设中的结果是写的右边的,state用来切换假设是轻还是重
//轻重的假设是通过切换pLeft和pRight的指向做到的
//默认假设是轻的
{
	char *pLeft,*pRight;
	for(int i=0;i<3;i++)
	{
		if(state==LIGHT)
		{
			pLeft=left_coin[i];
			pRight=right_coin[i];
		}
		else
		{
			pLeft=right_coin[i];
			pRight=left_coin[i];
		}
		switch(result[i][0])//通过结果的首字母来确定是哪个结果
		{
			case 'e'://两边平衡时
				if(isInvolved(coin,pLeft)||isInvolved(coin,pRight))//如果结果是平衡,有异常的硬币不应该在两边
					return false;
				break;
			case 'u'://右边up,即结果反映轻的在右边
				if(!isInvolved(coin,pRight))//默认硬币是轻的,就应该在右边
					return false;
				break;
			case 'd'://右边down<=>左边up
				if(!isInvolved(coin,pLeft))
					return false;
				break;
		}	
	}
	return true;//只有在三组数据都没报错,才会返回正确,中间只要有一组错就错了
}

bool isInvolved(char ch,char *str)
{
	while(*str!='\0')
	{
		if(*str==ch)
			return true;
		str++;
	}
	return false;
}

猜你喜欢

转载自blog.csdn.net/weixin_43873801/article/details/87632454