12月30号自习总结

目录

刷题:

八皇后

验证栈序列:

Corn Maze

临时佛脚


刷题:

八皇后

[USACO1.5]八皇后 Checker Challenge - 洛谷

题目描述

一个如下的 6×66×6 的跳棋棋盘,有六个棋子被放置在棋盘上,使得每行、每列有且只有一个,每条对角线(包括两条主对角线的所有平行线)上至多有一个棋子。

上面的布局可以用序列 2 4 6 1 3 52 4 6 1 3 5 来描述,第 ii 个数字表示在第 ii 行的相应位置有一个棋子,如下:

行号 1 2 3 4 5 61 2 3 4 5 6

列号 2 4 6 1 3 52 4 6 1 3 5

这只是棋子放置的一个解。请编一个程序找出所有棋子放置的解。
并把它们以上面的序列方法输出,解按字典顺序排列。
请输出前 33 个解。最后一行是解的总个数。

输入格式

一行一个正整数 nn,表示棋盘是 n×nn×n 大小的。

输出格式

前三行为前三个解,每个解的两个数字之间用一个空格隔开。第四行只有一个数字,表示解的总数。

输入输出样例

输入 #1

6

输出 #1

2 4 6 1 3 5
3 6 2 5 1 4
4 1 5 2 6 3
4

说明/提示

【数据范围】
对于 100%100% 的数据,6≤n≤136≤n≤13。

题目翻译来自NOCOW。

USACO Training Section 1.5

 思路:深度优先搜索(DFS)

详细思路:先看题目关键点,“每行、每列有且只有一个,每条对角线(包括两条主对角线的所有平行线)上至多有一个棋子”那么很容易想到dfs,那么先开辟3个一维数组,分别用来标记每列以及左斜和右斜对角线,用一个初始化为0的二维数组表示棋子具体放在哪个坐标点,,用当前已经放了多少个棋子来表示下一个棋子应该放第几层,每当棋子符合要求地放完即通过二维数组输出每个棋子所在的列数,然后回溯继续找其它方案;

code:

#include<stdio.h>
int arr[14][14] ; //放了棋子的地方标1;
int vis[14] ; //0表示该列没有被选
int su[40] ; //'/'    对角线,0表示没被选
int hu[400];//'\'对角线,0表示没有被选
int n, all = 0;
void print() {
	all++;
	if (all > 3) {
		return;
	}
	for (int i = 1; i <= n; i++) {
		for (int il = 1; il <= n; il++) {
			if (arr[i][il] == 1) {
				printf("%d ", il);
			}
		}
	}
	printf("\n");
}
void dfs(int num) { //numb表示当前所用棋子数和当前层数
	if (num == n + 1) { //棋子用完了
		print();
		return;
	}
	for (int i = 1; i <= n; i++) {
		if (vis[i] == 0 && su[num + i] == 0 && hu[num - i+100] == 0) { //该列及对角线还没有被选
			vis[i] = 1;//就是这里,我写成了vis[i]==1,检查了很多次才看出来
			arr[num][i] = 1;
			hu[num - i+100] = 1;//加上100是为了防止出现负数导致数组越界
			su[num + i] = 1;
			dfs(num + 1);
            //回溯
			hu[num - i+100] = 0;
			su[num + i] = 0;
			arr[num][i] = 0;
			vis[i] = 0;
		}
	}
}
int main() {
	scanf("%d", &n);
	dfs(1);
	printf("%d", all);
	return 0;
}

 

验证栈序列:

【深基15.习9】验证栈序列 - 洛谷

题目描述

给出两个序列 pushed 和 poped 两个序列,其取值从 1 到 n(n≤100000)n(n≤100000)。已知入栈序列是 pushed,如果出栈序列有可能是 poped,则输出 Yes,否则输出 No。为了防止骗分,每个测试点有多组数据。

输入格式

第一行一个整数 qq,询问次数。

接下来 qq 个询问,对于每个询问:

第一行一个整数 nn 表示序列长度;

第二行 nn 个整数表示入栈序列;

第三行 nn 个整数表示出栈序列;

输出格式

对于每个询问输出答案。

输入输出样例

输入 #1

2
5
1 2 3 4 5
5 4 3 2 1
4
1 2 3 4
2 4 1 3

输出 #1

Yes
No

基本思路:栈

详细思路:

将两个序列分别存储到两个数组里面,用一个for循环将入栈序列的数一个个入栈,每入栈一个数就看当前栈顶与出栈序列的最前面的数是否相等,相等则进入while循环将栈顶的数弹出,将出栈序列最前面的数删除,然后再看出栈序列接下来的一个数是否和栈顶的数相等,若相等再执行相同操作,一直到栈空或不相等结束while循环,再接着入栈。最后通过栈是否为空来判断输出Yes还是No;

代码:

#include<bits/stdc++.h>
struct stack {//栈
	int data[200000];
	int top;
};
int b[200000], a[200000];//暂时存储序列
int main() {
	int t;
	stack ui;
	//ui.top = 0; //栈初始化(不能放在这里,要放在for循环里面,不然会WA)
	scanf("%d", &t);
	for (int i = 0; i < t; i++) {   
		int n;
		ui.top=0;
		scanf("%d", &n);
		for (int ip = 0; ip < n; ip++) {
			scanf("%d", &a[ip]);
		}
		int x=0;
		for (int ip = 0; ip < n; ip++) {
			scanf("%d", &b[ip]);
		}
        //输入数据
		for (int ip = 0; ip < n; ip++) {
			ui.data[ui.top++]=a[ip];//入栈
			while(ui.data[ui.top-1]==b[x]){//相等
				x++;
				ui.top--;
				if(ui.top==0){//栈空
					break;
				}
			}
		}
		if(ui.top==0){
			printf("Yes\n");//注意大小写
		}else{
			printf("No\n");
		}
	}
	return 0;
}

Corn Maze

[USACO11OPEN]Corn Maze S - 洛谷

题目描述

This past fall, Farmer John took the cows to visit a corn maze. But this wasn't just any corn maze: it featured several gravity-powered teleporter slides, which cause cows to teleport instantly from one point in the maze to another. The slides work in both directions: a cow can slide from the slide's start to the end instantly, or from the end to the start. If a cow steps on a space that hosts either end of a slide, she must use the slide.

The outside of the corn maze is entirely corn except for a single exit.

The maze can be represented by an N x M (2 <= N <= 300; 2 <= M <= 300) grid. Each grid element contains one of these items:

* Corn (corn grid elements are impassable)

* Grass (easy to pass through!)

* A slide endpoint (which will transport a cow to the other endpoint)

* The exit

A cow can only move from one space to the next if they are adjacent and neither contains corn. Each grassy space has four potential neighbors to which a cow can travel. It takes 1 unit of time to move from a grassy space to an adjacent space; it takes 0 units of time to move from one slide endpoint to the other.

Corn-filled spaces are denoted with an octothorpe (#). Grassy spaces are denoted with a period (.). Pairs of slide endpoints are denoted with the same uppercase letter (A-Z), and no two different slides have endpoints denoted with the same letter. The exit is denoted with the equals sign (=).

Bessie got lost. She knows where she is on the grid, and marked her current grassy space with the 'at' symbol (@). What is the minimum time she needs to move to the exit space?

输入格式

第一行:两个用空格隔开的整数 NN 和 MM。

第 2∼N+12∼N+1 行:第 i+1i+1 行描述了迷宫中的第 ii 行的情况(共有MM个字符,每个字符中间没有空格)。

输出格式

一个整数,表示起点到出口所需的最短时间。

题意翻译

奶牛们去一个 N×MN×M 玉米迷宫,2≤N≤300,2≤M≤3002≤N≤300,2≤M≤300。

迷宫里有一些传送装置,可以将奶牛从一点到另一点进行瞬间转移。这些装置可以双向使用。

如果一头奶牛处在这个装置的起点或者终点,这头奶牛就必须使用这个装置。

玉米迷宫除了唯一的一个出口都被玉米包围。

迷宫中的每个元素都由以下项目中的一项组成:

  1. 玉米,# 表示,这些格子是不可以通过的。
  2. 草地,. 表示,可以简单的通过。
  3. 传送装置,每一对大写字母 AA 到 ZZ 表示。
  4. 出口,= 表示。
  5. 起点, @ 表示

奶牛能在一格草地上可能存在的四个相邻的格子移动,花费 11 个单位时间。从装置的一个结点到另一个结点不花时间。

输入输出样例

输入 #1

5 6
###=##
#.W.##
#.####
#.@W##
######

输出 #1

3

说明/提示

例如以下矩阵,N=5,M=6N=5,M=6。

###=##
#.W.##
#.####
#.@W##
######

唯一的一个装置的结点用大写字母 WW 表示。

最优方案为:先向右走到装置的结点,花费一个单位时间,再到装置的另一个结点上,花费 00 个单位时间,然后再向右走一个,再向上走一个,到达出口处,总共花费了 33 个单位时间。

思路:广度优先搜索(BFS)

本质上和迷宫那道题一样,但数据大点,并且只是多了个传送,用广度很容易就可以写出来;

详细思路:

用一个二维字符数组表示玉米地,一个二维数组来标记是否走过,一个三维数组来记录各点传送门传送到的坐标;输入数据,遍历找到起点,终点,各个传送门的坐标及其传达到的坐标,然后就可以开始平平无奇的BFS了;

具体看代码:

#include<bits/stdc++.h>
int n, m, fx, fy, ex, ey;
char maps[400][400];//地图
int next[4][2] = {{0, 1}, {1, 0}, {-1, 0}, {0, -1}};//方向数组
int bb[400][400] = {0}; //标记是否走过
int fly[400][400][3] = {0}; //用来记录是否是传送装置,以及传送到的另一端坐标
struct queue { //队列
	int x;
	int y;
	int tt;//奶牛走到该点所用时间
} liu[400 * 400 + 40];
int main() {
	scanf("%d %d", &n, &m);
	getchar();
	for (int i = 0; i < n; i++) {
		for (int li = 0; li < m; li++) {
			scanf("%c", &maps[i][li]);
			if (maps[i][li] == '@') { //记录起点坐标
				fx = i, fy = li;
			}
			if (maps[i][li] == '=') { //记录终点坐标
				ex = i, ey = li;
			}
		}
		getchar();
	}
	//输入数据
	for (int i = 0; i < n; i++) {
		for (int li = 0; li < m; li++) {
			if (fly[i][li][0] == 0 && (maps[i][li] >= 'A' && maps[i][li] <= 'Z')) { //是个传送装置且没有被标记过
				fly[i][li][0] = 1;//将第一次发现的传送装置标记
				for (int it = i; it < n; it++) { //找该传送装置的另外一个节点
					for (int ti = 0; ti < m; ti++) {
						if (maps[it][ti] == maps[i][li]) {
							fly[it][ti][0] = 1;
							//记录传送桥两端坐标
							fly[it][ti][1] = i;
							fly[it][ti][2] = li;
							fly[i][li][1] = it;
							fly[i][li][2] = ti;
						}
					}
				}
			}
		}
	}
	int head = 0, tail = 1; //队列初始化
	bb[fx][fy] = 1; //标记起点走过
	liu[head].x = fx, liu[head].y = fy, liu[head].tt = 0;//起点做队首
	while (head < tail) { //开始BFS(队列不为空)
		int sx = liu[head].x, sy = liu[head].y, st = liu[head].tt; //将队首队员取出
		head++;//队首删除
		for (int i = 0; i < 4; i++) {
			int dx = sx + next[i][0], dy = sy + next[i][1], dt = st + 1;
			if (bb[dx][dy] == 1 || dx >= n || dy >= m || dx < 0 || dy < 0 || maps[dx][dy] == '#') { //是否走过,越界,有玉米
				continue;
			}
			if (maps[dx][dy] >= 'A' && maps[dx][dy] <= 'Z') { //是传送点
				int hx = fly[dx][dy][1], hy = fly[dx][dy][2]; //传送(要重新定义一个hx和hy,再入队)
				//bb[hx][hy] = 1; //给被传送之后的点标记(不能标记,标记了就WA了)QWQ,码的,题目又没有说清楚
				liu[tail].x = hx, liu[tail].y = hy;
				liu[tail].tt = dt;//给被传送之后的点入队
				tail++;
				continue;
			}
			bb[dx][dy] = 1;//将新的可走点走过并标记
			if (dx == ex && dy == ey) {//看是否到了终点
				printf("%d", dt);
				return 0;
			}
			liu[tail].x = dx, liu[tail].y = dy;
			liu[tail].tt = dt;//将新的可走点入队
			tail++;
		}
	}
	return 0;
}

临时佛脚

kkksc03考前临时抱佛脚 - 洛谷

题目背景

kkksc03 的大学生活非常的颓废,平时根本不学习。但是,临近期末考试,他必须要开始抱佛脚,以求不挂科。

题目描述

这次期末考试,kkksc03 需要考 44 科。因此要开始刷习题集,每科都有一个习题集,分别有 s1,s2,s3,s4s1​,s2​,s3​,s4​ 道题目,完成每道题目需要一些时间,可能不等(A1,A2,…,As1A1​,A2​,…,As1​​,B1,B2,…,Bs2B1​,B2​,…,Bs2​​,C1,C2,…,Cs3C1​,C2​,…,Cs3​​,D1,D2,…,Ds4D1​,D2​,…,Ds4​​)。

kkksc03 有一个能力,他的左右两个大脑可以同时计算 22 道不同的题目,但是仅限于同一科。因此,kkksc03 必须一科一科的复习。

由于 kkksc03 还急着去处理洛谷的 bug,因此他希望尽快把事情做完,所以他希望知道能够完成复习的最短时间。

输入格式

本题包含 55 行数据:第 11 行,为四个正整数 s1,s2,s3,s4s1​,s2​,s3​,s4​。

第 22 行,为 A1,A2,…,As1A1​,A2​,…,As1​​ 共 s1s1​ 个数,表示第一科习题集每道题目所消耗的时间。

第 33 行,为 B1,B2,…,Bs2B1​,B2​,…,Bs2​​ 共 s2s2​ 个数。

第 44 行,为 C1,C2,…,Cs3C1​,C2​,…,Cs3​​ 共 s3s3​ 个数。

第 55 行,为 D1,D2,…,Ds4D1​,D2​,…,Ds4​​ 共 s4s4​ 个数,意思均同上。

输出格式

输出一行,为复习完毕最短时间。

输入输出样例

输入 #1

1 2 1 3		
5
4 3
6
2 4 3

输出 #1

20

说明/提示

1≤s1,s2,s3,s4≤201≤s1​,s2​,s3​,s4​≤20。

1≤A1,A2,…,As1,B1,B2,…,Bs2,C1,C2,…,Cs3,D1,D2,…,Ds4≤601≤A1​,A2​,…,As1​​,B1​,B2​,…,Bs2​​,C1​,C2​,…,Cs3​​,D1​,D2​,…,Ds4​​≤60。

思路

数据较小,可以用dfs(主要是我还不会dp),左右脑分开来看,一项任务要么左脑做,要么右脑,用的总时间是左右脑中耗时较大的那个,故直接遍历所有任务分配的方案,找出最小的max(l,r)即为该科所用最少时间;

code:

#include<stdio.h>
#include<string.h>
int aa[4], sz[80];
int all = 0;
int bj[80] = {0};
int yu, temp, r, l;
int min(int x, int y) {
	return x > y ? y : x;
}
int max(int x, int y) {
	return y > x ? y : x;
}
void dfs(int x) {//x表示目前已选个数
	if (x == yu ) {
		temp = min(temp, max(r, l));
		return;
	}
	l += sz[x];
	dfs(x + 1);
	l -= sz[x];
	r += sz[x];
	dfs(x + 1);
	r -= sz[x];
}
int main() {
	for (int i = 0; i < 4; i++) {
		scanf("%d", &aa[i]);
	}
	for (int i = 0; i < 4; i++) {
		memset(bj, 0, sizeof(bj));
		yu = aa[i];
		temp = 666666666, r = 0, l = 0;//初始化
		for (int io = 0; io < yu; io++) {
			scanf("%d", &sz[io]);
		}
		dfs(0);

		all += temp;
	}
	printf("%d", all);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值