贪心,怎么贪的有意思?1033 To Fill or Not to Fill,1067 Sort with Swap(0, i),1038 Recover the Smallest Number

文章目录

    • 1033 To Fill or Not to Fill (25分)
      • 试题内容
      • 试题分析
    • 1067 Sort with Swap(0, i) (25分)
      • 试题内容
      • 试题分析
    • 1038 Recover the Smallest Number (30分)
      • 试题内容
      • 题目解析
    • 补充知识set
      • set(集合)
        • set的定义
        • set内元素的访问
        • set常用函数:

1033 To Fill or Not to Fill (25分)

试题内容

With highways available, driving a car from Hangzhou to any other city is easy. But since the tank capacity of a car is limited, we have to find gas stations on the way from time to time. Different gas station may give different price. You are asked to carefully design the cheapest route to go.

Input Specification:
Each input file contains one test case. For each case, the first line contains 4 positive numbers: C
​max(≤ 100), the maximum capacity of the tank; D (≤30000), the distance between Hangzhou and the destination city; D​avg(≤20), the average distance per unit gas that the car can run; and N (≤ 500), the total number of gas stations. Then N lines follow, each contains a pair of non-negative numbers: P​i, the unit gas price, and D​i​​ (≤D), the distance between this station and Hangzhou, for i=1,⋯,N. All the numbers in a line are separated by a space.

Output Specification:
For each test case, print the cheapest price in a line, accurate up to 2 decimal places. It is assumed that the tank is empty at the beginning. If it is impossible to reach the destination, print The maximum travel distance = X where X is the maximum possible distance the car can run, accurate up to 2 decimal places.

Sample Input 1:
50 1300 12 8
6.00 1250
7.00 600
7.00 150
7.10 0
7.20 200
7.50 400
7.30 1000
6.85 300
Sample Output 1:
749.17
Sample Input 2:
50 1300 12 2
7.10 0
7.00 600
Sample Output 2:
The maximum travel distance = 1200.00

试题大意:
汽⻋从杭州出发可以通过⾼速公路去任何城市,但是油箱的容量是有限的,路上有很多加
油站,每个加油站的价格不同,为汽⻋设计⼀个从杭州到终点的最便宜的路线, Cmax表示油箱最⼤容
量, D表示杭州到⽬的地的距离, Davg表示平均每单位的汽油可以让汽⻋⾏驶的距离, N表示汽⻋的站
点数量,每个站点都会给出它的单位油价Pi和汽⻋站点和杭州的距离Di,求汽⻋从杭州到终点的最⼩
花费,如果不能够到达,就输出汽⻋能够⾏驶的最⼤距离

试题分析

主要思路

  1. 寻找⽐⾃⼰距离远的,到能够到达的最⼤距离之间的加油站,看他们的油价。如果找到了更低价格的油价,就加油到刚好能到达那个加油站的距离的油。
  2. 如果找不到更低的,就找尽可能低的油价的加油站,在当前加油站加满油之后过去。
  3. 如果在满油状态下都找不到能到达的加油站,则结束,输出当下最多能达到了距离。

易错

  1. 在距离为0处必须有加油站,否则无法出发
  2. 除了n是整形外,其他的都应该是double

#include 
#include 
#include 
using namespace std;

int n;
double c,d,vd;
struct Move{
	double p;
	double l;
}car[510];
const double INF = 9999999.99; 
double maxd;
double now ,nowrest ,ansp ,ansl;
bool cmp(Move a,Move b){
	if(a.l == b.l) return a.p<b.p;
	else return a.l<b.l;
}
void add1(int a,int b){
	ansl += car[a].l-car[b].l-nowrest;
	ansp += (car[a].l-car[b].l-nowrest)/vd*car[b].p;	
	nowrest = 0;
}

void add2(int a,int b){
	ansl += maxd;
	ansp += (maxd-nowrest)/vd*car[b].p;
	nowrest = maxd-(car[a].l-car[b].l);	//开车到下一个加油站的剩余可以行驶的距离
}

int juge(int index){
	bool flag = false;
	double pricemine = INF;
	int pid = -1;
	for(int i=index+1;i<=n&&car[i].l-car[index].l<=maxd;i++){
		if(pricemine>car[i].p){
			pid = i;
			pricemine = car[i].p;
			if(pricemine < car[index].p) {
				flag = true;
				add1(pid,index);
				index = pid;
				break;
			}
		}
	}
	if(pricemine == INF) return -1;
	else if(!flag) {
		add2(pid,index);
		index = pid;
	}
	return index;
}


int main(){
	scanf("%lf%lf%lf%d",&c,&d,&vd,&n);
	maxd = c*vd;
	car[0].l = d;car[0].p = 0; 
	for(int i=1;i<=n;i++){
		scanf("%lf%lf",&car[i].p,&car[i].l);
	}
	sort(car,car+n+1,cmp);
	if(car[0].l != 0) printf("The maximum travel distance = 0.00\n");
	else{
		now = 0.0,nowrest = 0.0,ansp = 0.0,ansl = 0.0;
		while(now <n){
			now = juge(now);
			if(now == -1) break;
		}
		if(now == -1) printf("The maximum travel distance = %.2f\n",ansl+maxd);
		else printf("%.2f\n",ansp);
	}
	return 0;
}

1067 Sort with Swap(0, i) (25分)

试题内容

Given any permutation of the numbers {0, 1, 2,…, N−1}, it is easy to sort them in increasing order. But what if Swap(0, *) is the ONLY operation that is allowed to use? For example, to sort {4, 0, 2, 1, 3} we may apply the swap operations in the following way:

Swap(0, 1) => {4, 1, 2, 0, 3}
Swap(0, 3) => {4, 1, 2, 3, 0}
Swap(0, 4) => {0, 1, 2, 3, 4}

Now you are asked to find the minimum number of swaps need to sort the given permutation of the first N nonnegative integers.

Input Specification:
Each input file contains one test case, which gives a positive N (≤10​5) followed by a permutation sequence of {0, 1, …, N−1}. All the numbers in a line are separated by a space.

Output Specification:
For each case, simply print in a line the minimum number of swaps need to sort the given permutation.

Sample Input:
10
3 5 7 2 6 4 9 0 8 1
Sample Output:
9

试题分析

试题题解
给出⼀个n个数的序列,数字为0~n-1的乱序,每次⽤两两交换的⽅式⽽且只能⽤0和另⼀个数交换,使序列变成有序的,问最少需要多少步骤。

试题易错
超时,在判断是否已经配对完全时,需要遍历访问数组,指数级则会超时。

#include 
#include 
using namespace std;
set <int> st;
const int mmax = 100010;
int a[mmax],n,table[mmax];


int main(){
	scanf("%d",&n);
	int count = 0;
	for(int i=0;i<n;i++){
		scanf("%d",&a[i]);
		table[a[i]] = i;
		st.insert(i);
	}
	int index = table[0],t=0;
	while(1){
		if(index == 0){
			for(set<int>::iterator it = st.begin();it!=st.end();it++){
				if(table[a[*it]]!=a[*it]&&a[*it]!=0) { //从第一个没有配对的开始,否是会超时 
					index = *it;
					table[a[*it]] = 0;
					t = table[*it];
					count++;
					break;
				}
			}
			if(index==0) break;	
		}
		else{
			t = table[index];  
		}
		table[index] = index;
		st.erase(index);//删除已经配对好的元素 
		//printf("table[%d] = %d\n",index,index);
		index = t;
		count++;
	}
	printf("%d\n",count);
	return 0;	
}
#include 
#include 
using namespace std;
const int mmax = 100010;
int n;
int a[mmax],t;

int main(){
	scanf("%d",&n);
	for(int i=0;i<n;i++){
		scanf("%d",&t);
		a[t] = i;
	} 
	int count = 0;
	for(int i=1;i<n;i++){
		if(a[i]!=i){
			while(a[0]!=0){
				swap(a[0],a[a[0]]); //直接使用swap交换后,让顺序替换
				count++;
			}
			if(i!=a[i]){
				swap(a[0],a[i]);
				count++;
			}
		}
	}
	printf("%d\n",count);
	return 0;
} 

1038 Recover the Smallest Number (30分)

试题内容

Given a collection of number segments, you are supposed to recover the smallest number from them. For example, given { 32, 321, 3214, 0229, 87 }, we can recover many numbers such like 32-321-3214-0229-87 or 0229-32-87-321-3214 with respect to different orders of combinations of these segments, and the smallest number is 0229-321-3214-32-87.

Input Specification:
Each input file contains one test case. Each case gives a positive integer N (≤10​4 ) followed by N number segments. Each segment contains a non-negative integer of no more than 8 digits. All the numbers in a line are separated by a space.

Output Specification:
For each test case, print the smallest number in one line. Notice that the first digit must not be zero.

Sample Input:
5 32 321 3214 0229 87
Sample Output:
22932132143287

题目解析

试题大意
给⼀些字符串,求它们拼接起来构成最⼩数字的⽅式

#include 
#include 
#include 
#include 
using namespace std;
const int mMax = 10010;
string s[mMax];
int n;
bool cmp(string a,string b){
	return a+b < b+a; //相加直接拼接
}
int main(){
	scanf("%d",&n);
	for(int i=0;i<n;i++){
		cin>>s[i];
	}
	sort(s,s+n,cmp);
	string ans;
	for(int i=0;i<n;i++){
		ans += s[i];
	}
	while (ans[0]=='0'&&ans.length()!=0){
		ans.erase(ans.begin());
	}
	if(ans.length() == 0) cout<<0<<endl;
	else cout<<ans<<endl;
	return 0;	
}

补充知识set

set(集合)

因为是集合所以有着互异性,set里面的各元素是各不相同的,而且set会按照元素进行从小到大排序

set的定义

set s; 定义一个空集合s,其中typename 中可以是double,结构体,类,或者是其他容器。
set t[n] ; 则每个t[0]~t[n-1]每一个都是一个set容器。

set内元素的访问

只能通过迭代器访问,例如:set :: iterator it;

for(set \<int> ::iterator it = s.begin();it!= s.end(
;it++){
		printf("%d",*it)
}

或者,将set ::iterator 用auto 表示

set常用函数:

  1. insert()
for (int i = 0; i < 6; i++) {
s.insert(i); // 向集合s⾥⾯插⼊i
}
  1. find()
*(s.find(2))  // 如果2存在,则printf 结果为2。
s.find(2)!=s.end() // 判断该元素是否存在
  1. erase()
    s.erase(s.find(1)) // 删除单个元素 ,这个方法空间复杂度为0(1)
    s.erase(100) // 删除的单个元素,这个是个为O(logn)
    s.erase(s.find(300),s.end()) // 删除元素300到set末尾之间的元素
  2. size()
    所有容器通用的获得容器大小的函数。
    s.size()
  3. clear()
    s.clear() //清空set 容器,则s.size() = 0;

勉励
加油
贪心,思路清晰很重要!!!

你可能感兴趣的:(PAT,甲级)