数据结构与算法复习:第三十七弹

1061 Dating

题目链接
分析:这是一道非常考察隐藏点的题目,也就是说对于“星期”其实字母必须是在[A,G]之间,关于小时的确定必须是在星期的确定之后,也就是遍历的位置是在星期代表的字母之后,注意范围[0,9]或者[A,N],最后分钟的确定没有歧义,就是最后两个字符串第一个共享字母的位置(从0开始编号)

#include<bits/stdc++.h>
using namespace std;
string a,b,c,d;
string week[]={"","MON","TUE","WED","THU","FRI","SAT","SUN"};
int dd=0,hh=0,mm=0;
int main(){
	cin>>a>>b>>c>>d;
	int i;
	int len=min(a.length(),b.length());
	for(i=0;i<len;i++){
		if(a[i]<='G'&&a[i]>='A'&&a[i]==b[i]){
			dd=a[i]-'A'+1;
			break;
		}
	}
	i++;
	for(;i<len;i++){
		if(a[i]<='9'&&a[i]>='0'&&a[i]==b[i]){
			hh=a[i]-'0';
			break;
		}
        if(a[i]<='N'&&a[i]>='A'&&a[i]==b[i]){
			hh=a[i]-'A'+10;
			break;
		}
	}
	for(i=0;i<min(c.length(),d.length());i++){
		if(c[i]==d[i]&&isalpha(c[i])){
			mm=i;
			break;
		}
	}
	printf("%s %02d:%02d",week[dd].c_str(),hh,mm);
	return 0;
} 

1160 Forever

【题目链接】
“Forever number” is a positive integer A with K digits, satisfying the following constrains:

  • the sum of all the digits of A is m;
  • the sum of all the digits of A+1 is n; and
  • the greatest common divisor of m and n is a prime number which is greater than 2.

Now you are supposed to find these forever numbers.

Input Specification:

Each input file contains one test case. For each test case, the first line contains a positive integer N (≤5). Then N lines follow, each gives a pair of K (3<K<10) and m (1<m<90), of which the meanings are given in the problem description.

Output Specification:

For each pair of K and m, first print in a line Case X, where X is the case index (starts from 1). Then print n and A in the following line. The numbers must be separated by a space. If the solution is not unique, output in the ascending order of n. If still not unique, output in the ascending order of A. If there is no solution, output No Solution.

Sample Input:

2
6 45
7 80

Sample Output:

Case 1
10 189999
10 279999
10 369999
10 459999
10 549999
10 639999
10 729999
10 819999
10 909999
Case 2
No Solution

解析:
我们知道要想满足情况,A必须是以9结尾,那么因为A的由K个数字组成,数位和为m,那么假设A末尾9的个数是num9个则n=m+1-num9*9,如果n,m满足题目的条件,最大公因数是大于2的素数,那么dfs深搜得到A的可能值,需要注意因为末尾9的个数确定了,所以深搜的最后一个数字不可以为9(卡了半天卡在这里😅,午饭差点没了)

#include<bits/stdc++.h>
using namespace std;
int N,K,m,n,num9;
struct Node{
	int n;
	int v;
};
vector<Node>ans;
bool isPrime(int x){
	if(x<=2){
		return false;
	}
	for(int i=2;i*i<=x;i++){
		if(x%i==0){
			return false;
		}
	}
	return true;
} 
bool cmp(Node a,Node b){
	if(a.n!=b.n){
		return a.n<b.n;
	}else{
		return a.v<b.v;
	}
}
void dfs(int len,int sum,int num,int tmp){
	len--;
	sum-=num;
	tmp=tmp*10+num;
	if(len==0){
		if(sum==0&&num!=9){//这里!!!!!
			for(int i=0;i<num9;i++){
				tmp=tmp*10+9;
			}
			Node temp;
			temp.n=n;
			temp.v=tmp;
			ans.push_back(temp);
		}
	}else if(len>0){
		for(int i=0;i<=9;i++){
			if(i<=sum){
				dfs(len,sum,i,tmp);
			}else{
				break;
			}
		}
	}
}
int main(){
	scanf("%d",&N);
	for(int i=1;i<=N;i++){
		printf("Case %d\n",i);
		scanf("%d%d",&K,&m);
		ans.clear();
		for(num9=1;num9<=K;num9++){
			if(m<num9*9){
				break;
			}
			n=m-num9*9+1;
			if(isPrime(__gcd(m,n))){
				//搜合法的值
				for(int i=1;i<=9;i++){
					if(i<=m-num9*9){
						dfs(K-num9,m-num9*9,i,0);
					}
				}
			}
		}
		if(ans.size()==0){
			printf("No Solution\n");
		}else{
			sort(ans.begin(),ans.end(),cmp);
			for(int i=0;i<ans.size();i++){
				printf("%d %d\n",ans[i].n,ans[i].v);
			}
		}
	}
	return 0;
}

1033 To Fill or not to Fill

题目链接
个人感觉是比较难的贪心算法的题目了,可能练的比较少……
原来写的是23/25

#include<bits/stdc++.h>
using namespace std;
double Cmax,Dis,Davg;
int N;
struct Station{
	double d;//离起点的距离
	double price;//每一升油价 
};
const int maxn=99999999;
double cost=0;
double _distance=0;
double prePrice;
double curPrice;
vector<Station>station;
bool cmp(Station a,Station b){
	return a.d<b.d;
}
int getNextStationId(int id,double &curPrice,double price){
	//当前能够走到的距离中最合算的 
	int ans_id=-1;
	double min_price=double(maxn);
	for(int i=id+1;i<N;i++){
		
		if(station[i].d>_distance){
			break;
		}
		if(station[i].price<=min_price){
			min_price=station[i].price;
			ans_id=i;
			if(min_price<=price){
				break;
			}
		}
	}
	if(ans_id!=-1){
		curPrice=min_price;
	}
	
	return ans_id;
}
int main(){
	scanf("%lf%lf%lf%d",&Cmax,&Dis,&Davg,&N);
	station.resize(N);
	for(int i=0;i<N;i++){
		scanf("%lf%lf",&station[i].price,&station[i].d);
	}
	sort(station.begin(),station.end(),cmp);
	//下面开始贪心策略
	if(station[0].d!=0){
		printf("The maximum travel distance = 0.00");
	}else{
		//一开始出发的消耗
		_distance=Cmax*Davg;
		cost+=Cmax*station[0].price;
		prePrice=station[0].price;
		double pre_dis=0;
		int id=0;
//		printf("cost=%.2f,id=%d,curPrice=%.2f,distance=%.2f\n",cost,id,curPrice,_distance);
		while(1){
			
			id=getNextStationId(id,curPrice,prePrice);
			
			if(id==-1){
				//没找到目标
				if(_distance>=Dis){
					break;
				}else{
					printf("The maximum travel distance = %.2f",_distance);
					break; 
				}
			}else{
				if(prePrice<curPrice){
					cost+=((station[id].d-pre_dis)/Davg)*curPrice;//装满即可 
				}else{
					cost-=(Cmax-(station[id].d-pre_dis)/Davg)*prePrice;//倒掉,全部换成新的 
					cost+=curPrice*Cmax;
				} 
//				printf("now cost:%.2f\n",prePrice*(station[id].d-pre_dis)/Davg);
				//更新价格 
				prePrice=curPrice; 
				//更新距离
				_distance=station[id].d+Cmax*Davg;
				pre_dis=station[id].d; 
			}
//			printf("cost=%.2f,id=%d,curPrice=%.2f,distance=%.2f\n",cost,id,curPrice,_distance);
		}
		if(_distance>=Dis){
			//处理
//			printf("now cost:%.2f\n",prePrice*(Dis-pre_dis)/Davg);
			cost-=(Cmax-(Dis-pre_dis)/Davg)*prePrice;
			printf("%.2f",cost); 
		}
		
		 
	}
	return 0;
} 

后来看了柳神的思路自己写了一遍……
主要在于left_dis这个变量的构造,贪心分三种情况:

  • 在当前加油站范围先找离他最近的价格低于它的,然后加油至于刚好可以到达最近的价格略低的加油站(最简单的情况)
  • 如果范围内没有油价低于自己的,则现在需要加满,记录到达当前可以抵达的最远的加油站的消耗(此时需要引入res_dis即next_station_pos-cur_dis的差值,且在接下来计算油价的时候需要及时更新res_dis)
  • 如果当前范围找不到下一个落脚点,则记录当前能到达的最远距离,若距离大于D则说明我们可以抵达目的地,此时需要根据距离目的地距离计算总消费,反之则不行,输出最大距离
#include<bits/stdc++.h>
using namespace std;
double Cmax,D,Davg;
int N;
struct Station{
	double price;
	double d;
	bool operator <(Station b)const{
		return this->d<b.d;
	}
};
Station temp;
vector<Station>st;
int main(){
	scanf("%lf%lf%lf%d",&Cmax,&D,&Davg,&N);
	double price,d;
	while(N--){
		scanf("%lf%lf",&price,&d);
		if(d>=D){
			continue;
		}else{
			temp.price=price;
			temp.d=d;
			st.push_back(temp);
		}
	}
	double cur_dis=0,cur_price=0,max_dis=0;
	double left_dis=0;
	int index=0;
	int len=st.size();
	sort(st.begin(),st.end());
	if(st[0].d>0){
		printf("The maximum travel distance = 0.00");
		return 0;
	}
	while(cur_dis<D){
		max_dis=cur_dis+Cmax*Davg;
		int type=0;
		double min_price=999999;
		int nid=-1;
	//	cout<<"index="<<index<<" cost="<<cur_price<<" dis="<<cur_dis<<"\n";
		for(int i=index+1;i<len;i++){
			if(st[i].d>max_dis){
				break;
			}
			if(st[i].price<st[index].price){
				type=1;//找到了距离最近的价格低的车站
				cur_dis=st[i].d;
				cur_price+=(st[i].d-st[index].d-left_dis)*st[index].price/Davg;
				index=i;
				left_dis=0;
				break; 
			}
			if(st[i].price<min_price){
				min_price=st[i].price;
				nid=i;
				type=2;
			}
		}
		if(type==2){
			if(D<=max_dis){//如果没有比它更小的,且现在也能开到结束 
				cur_price+=(D-st[index].d-left_dis)*st[index].price/Davg;
				cur_dis=D;
			}else{
				cur_price+=(Cmax-left_dis/Davg)*st[index].price;//加满
				left_dis=max_dis-st[nid].d; 
				cur_dis=st[nid].d;
				index=nid;
			}
		}else if(type==0){
			if(D<=max_dis){
				cur_price+=(D-st[index].d)*st[index].price/Davg;
				cur_dis=D;
			}else{
				cur_dis=max_dis;
			} 
			break;
		}
	}
	if(cur_dis<D){
		printf("The maximum travel distance = %.2f",cur_dis);
	}else{
		printf("%.2f",cur_price);
	}
	return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值