• 0930上午考试


    0930上午考试

    T1

    ​ 题目大意:

    ​ Nescafe之塔一共有N层,升降梯在每层都有一个停靠点。手柄有M个控制槽,第i个控制槽旁边标着一个数Ci,满足C1<C2<C3<......<CM。如果Ci>0,表示手柄扳动到该槽时,电梯将上升Ci层;如果Ci<0,表示手柄扳动到该槽时,电梯将下降-Ci层;并且一定存在一个Ci=0,手柄最初就位于此槽中。注意升降梯只能在1~N层间移动,因此扳动到使升降梯移动到1层以下、N层以上的控制槽是不允许的。电梯每移动一层,需要花费2秒钟时间,而手柄从一个控制槽扳到相邻的槽,需要花费1秒钟时间。探险队员现在在1层,并且想尽快到达N层,他们想知道从1层到N层至少需要多长时间?如果到不了就输出-1

    ​ 对于100%的数据,满足1≤N≤1000,2<=M<=20,-N<C1<C2<......<CM<N。

    ​ 好吧这道题我是完全不会。

    ​ 正解最短路,把现在在某一层,某个手柄作为状态,把手柄和升降梯的移动看做边,但是不用建边,思路还是很巧妙的。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    inline long long read() {
    	long long s = 0, f = 1; char ch;
    	while(!isdigit(ch = getchar())) (ch == '-') && (f = -f);
    	for(s = ch ^ 48;isdigit(ch = getchar()); s = (s << 1) + (s << 3) + (ch ^ 48));
    	return s * f;
    }
    
    const int M = 21, N = 1005, inf = 1e9;
    int n, m, z, ans;
    int a[N], vis[N][M], dis[N][M];
    
    struct node {
    	int dis, x, y;
    	node() {}
    	node(int D, int X, int Y) { dis = D, x = X, y = Y; }
    	friend operator > (const node &a, const node &b) { return a.dis > b.dis; }
    } ;
    
    void ran_dij() {
    	for(int i = 1;i <= n; i++) 
    		for(int j = 1;j <= m; j++) dis[i][j] = inf; 
    	priority_queue <node, vector<node>, greater<node> > q;
    	q.push(node(0, 1, z)); dis[1][z] = 0; 
    	while(!q.empty()) {
    		int x = q.top().x, y = q.top().y; q.pop();
    		if(vis[x][y]) continue; vis[x][y] = 1;
    		if(y != 1) {
    			int nowy = y - 1;
    			if(dis[x][nowy] > dis[x][y] + 1) {
    				dis[x][nowy] = dis[x][y] + 1;
    				q.push(node(dis[x][nowy], x, nowy));
    			}
    		}
    		if(y != m) {
    			int nowy = y + 1;
    			if(dis[x][nowy] > dis[x][y] + 1) {
    				dis[x][nowy] = dis[x][y] + 1;
    				q.push(node(dis[x][nowy], x, nowy));
    			}
    		}
    		int nowx = x + a[y];
    		if(nowx >= 1 && nowx <= n) {
    			if(dis[nowx][y] > dis[x][y] + 2 * abs(a[y])) {
    				dis[nowx][y] = dis[x][y] + 2 * abs(a[y]);
    				q.push(node(dis[nowx][y], nowx, y));
    			}
    		}
    	}
    }
    
    int main() {
    	
    	n = read(); m = read();
    	for(int i = 1;i <= m; i++) {
    		a[i] = read(); if(a[i] == 0) z = i;
    	}
    	ran_dij(); ans = inf;
    	for(int i = 1;i <= m; i++) ans = min(ans, dis[n][i]);
    	printf("%d", ans == inf ? -1 : ans);
    	
    	fclose(stdin); fclose(stdout);
    	return 0;
    }
    
    

    T2

    ​ 题目大意:

    ​ 王伯(不是王婆)退休后开始养鱼。他一早起床就赶去动物园,发现这个世界的鱼真不少,五光十色、色彩斑斓,大的、小的,什么都有。这些鱼实在是太美了,买的人越来越多,湖里的鱼越来越少。没有美丽的鱼哪里有美丽的湖?于是动物园不得不规定,对于每种鱼,每个人最多可以买一条。并且有些鱼不能一起买的,因为它们之间会相互争斗吞食。王伯想买尽可能多的鱼,但很可惜,他的资金有限。他冥想苦思,不知道如何是好。请编写一个程序帮助他。如果有多个方案都能买尽可能多的鱼,选择所花资金最多的一个。

    ​ 【输出格式】第一行为两个正整数X,Y,分别表示所买的鱼的条数和总花费。以下X行,每行有一个正整数,表示所买的鱼的编号。编号按升序排列输出。如果题目有多个解,输出其中字典序最小的一个。

    ​ 刚刚看题,二分图???又看了一会儿,二进制,绝对二进制。写了一个小时后,md写挂了,不能用二进制。算了写个迭代加深吧,20pts……(我吐了)

    ​ 正解是搜索,用到了xjb算法。????? 注意下剪枝就好了,细节还挺多的,刚开始以为编号没啥用,其实必须带上编号,还是得好好审题呀。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    inline long long read() {
    	long long s = 0, f = 1; char ch;
    	while(!isdigit(ch = getchar())) (ch == '-') && (f = -f);
    	for(s = ch ^ 48;isdigit(ch = getchar()); s = (s << 1) + (s << 3) + (ch ^ 48));
    	return s * f;
    }
    
    const int N = 40;
    int m, n, ans_sum, ans_cnt, id[N], getid[N], vis[N], tmp[N], ans[N];
    struct node { int id, x; } a[N];
    vector <int> v[N];
    
    int cmp(node a, node b) { return a.id < b.id; }
    
    void dfs(int now, int cnt, int sum) {
    	if(cnt + n - now + 1 < ans_cnt) return ; //如果无法更新已有最优解就返回
    	if(sum > m) return ; //如果王伯破产了就返回
    	if(now == n + 1) {
    		if(cnt > ans_cnt || (cnt == ans_cnt && sum > ans_sum)) { //这是更新答案的条件
    			for(int i = 1;i <= n; i++) ans[i] = tmp[i];
    			ans_cnt = cnt; ans_sum = sum;
    		}
    		return ;
    	}
    	if(!vis[now]) {
    		tmp[now] = 1;
    		for(int i = 0;i < (int)v[now].size(); i++) vis[v[now][i]] ++; //注意这里写自加或自减,不可直接赋为0或1
    		dfs(now + 1, cnt + 1, sum + a[now].x);
    		tmp[now] = 0;
    		for(int i = 0;i < (int)v[now].size(); i++) vis[v[now][i]] --; 
    	}
    	dfs(now + 1, cnt, sum);
    }
    
    int main() {
    	
    	m = read(); n = read();
    	for(int i = 1;i <= n; i++) 
    		a[i].id = read(), a[i].x = read();
    	sort(a + 1, a + n + 1, cmp);
    	for(int i = 1;i <= n; i++) getid[a[i].id] = i;
    	
    	while(666666) {
    		int x = read(), y = read(); if(x == 0 && y == 0) break;
    		x = getid[x], y = getid[y];
    		v[x].push_back(y); v[y].push_back(x);
    	}
    	dfs(1, 0, 0);
    
    	printf("%d %d
    ", ans_cnt, ans_sum);
    	for(int i = 1;i <= n; i++) 
    		if(ans[i]) printf("%d
    ", a[i].id);
    	
    	fclose(stdin); fclose(stdout);
    	return 0;
    }
    

    T3

    ​ 题目大意:

    ​ Freda和rainbow饲养了N只小猫,这天,小猫们要去爬山。经历了千辛万苦,小猫们终于爬上了山顶,但是疲倦的它们再也不想徒步走下山了。Freda和rainbow只好花钱让它们坐索道下山。索道上的缆车最大承重量为W,而N只小猫的重量分别是C1、C2......CN。当然,每辆缆车上的小猫的重量之和不能超过W。每租用一辆缆车,Freda和rainbow就要付1美元,所以他们想知道,最少需要付多少美元才能把这N只小猫都运送下山?

    ​ 考试时想的是贪心,但是贪心写炸了,从80pts -> 20pts。QWQ

    ​ 贪心的做法是按重量排序,先放大的再放小的,但是不对,比如这组数据:

    6 50
    20 20 15 15 15 15
    

    ​ 正解为2:{20, 15, 15}, {20, 15, 15};

    ​ 贪心为3:{20, 20}, {15, 15, 15}, {15}。

    ​ 所以还是写搜索了。我们搜到每一个小猫是都分两种情况:让它自己坐一辆,让它和别的猫挤一辆。加点优化:如果当前搜到的车的数量大于等于现有最大值,那么一定更新不了答案,直接返回;我们把猫从大到小排个序,因为大猫一定会比小猫更难放。

    #include <bits/stdc++.h>
    	
    using namespace std;
    	
    inline long long read() {
    	long long s = 0, f = 1; char ch;
    	while(!isdigit(ch = getchar())) (ch == '-') && (f = -f);
    	for(s = ch ^ 48;isdigit(ch = getchar()); s = (s << 1) + (s << 3) + (ch ^ 48));
    	return s * f;
    }
    	
    const int N = 20;
    int n, w, cnt, ans, a[N], tmp[N];
    
    int cmp(int a, int b) { return a > b; }
    
    void dfs(int now_cnt, int now) {
    	if(now_cnt >= ans) return ;
    	if(now == n + 1) { ans = min(ans, now_cnt); return ; }
    	for(int i = 1;i <= cnt; i++) {
    		if(tmp[i] >= a[now]) tmp[i] -= a[now], dfs(now_cnt, now + 1), tmp[i] += a[now];
    	}
    	tmp[++cnt] = w - a[now];
    	dfs(now_cnt + 1, now + 1);
    	cnt --;
    }
    
    int main() {
    
    	n = read(); w = read(); ans = 100;
    	for(int i = 1;i <= n; i++) a[i] = read();
    	sort(a + 1, a + n + 1, cmp);
    	dfs(0, 1); //缩索
    	printf("%d", ans);
    
    	fclose(stdin); fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    CCF-201803-3-URL映射(模拟)
    Problem UVA11134-Fabled Rooks(贪心)
    UVA1152-4 Values whose Sum is 0(分块)
    UVA1605-Building for UN(思维)
    基于XMPP的IOS聊天客户端程序(IOS端一)
    基于XMPP的IOS聊天客户端程序(XMPP服务器架构)
    正则表达式在iOS中的运用
    NSUserDefaults 简介,使用 NSUserDefaults 存储自定义对象
    自动无限循环UIScrollView原理
    NSTimeZone
  • 原文地址:https://www.cnblogs.com/czhui666/p/13757161.html
Copyright © 2020-2023  润新知