网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
dp滚动数组的雏形
还是递推写法,但是优化跟递推无关
我们可以发现,每一项只跟前两项有关系,因此我们可以省点空间,不开数组,直接开变量就可以,每次只记录前两项是多少。
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int a = 0, b = 1;
for (int i = 1; i <= n; i++) {
System.out.print(a + " ");
int fn = a + b;
a = b;
b = fn;
}
}
}
AcWing 95. 费解的开关
将所有灯变亮 也就是所有数字变为1
我们以输入的第二个5x5的数为例:
11101
11101
11110
11111
11111
怎么把所有灯变亮呢?
我们可以先灭掉(2,5),然后再涂右上角的就可以,两步完成,所以输出2。
灭掉(2,5),(2,4)(3,5)亮,(1,5)灭
此时的5x5数字为
11100
11110
11111
11111
11111
再将(1,5)也就是右上角点亮,(1,4)(2,5)亮,所有数字全亮。
此时数字为
11111
11111
11111
11111
11111
符合题目要求,两步完成,输出2。
思想:
每一行开关的操作完全被上一行灯的亮灭状态所唯一确定
我们只需要枚举第一行的操作,之后所有的操作都可以根据上一行的亮灭来进行操作; 第二行的操作完全取决于第一行,第一行操作完改变了第一行的状态,第一行的状态决定了第二行的操作,假如第一行操作完之后还有灭的,因为第一行不能操作了,所以我们只能按第二行来使第一行的灯全亮,同理,第三行的操作完全取决于第二行,以此类推。
顺序可以任意,每个格子最多按一次。
所以解法就是枚举第一行,之后的所有操作就都确定了。
最后一行的状态不能改了,需要特判一下,如果有灭着的说明方案不合法,如果全亮说明方案ok。
import java.util.Scanner;
public class Main {
static final int N = 6;
static char[][] g = new char[N][N];
static char[][] backup = new char[N][N]; // 备份数组
static int[] dx = {-1, 0, 1, 0, 0}; // 坐标x的偏移量
static int[] dy = {0, 1, 0, -1, 0}; // 坐标y的偏移量
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
while (n-- != 0) {
for (int i = 0; i < 5; i++) g[i] = sc.next().toCharArray();
int res = Integer.MAX_VALUE;
for (int op = 0; op < 32; op++) { // 5位数 转换成2进制最大的数是32
for (int i = 0; i < 5; i++) {
backup[i] = g[i].clone();
}
int step = 0;
// 对第一行状态的判断
for (int i = 0; i < 5; i++) {
if ((op >> i & 1) == 0) { // 判断i的二进制的第几位是不是1
step++;
turn(0, 4 - i);
}
}
// 对2,3,4行判断
for (int i = 0; i < 4; i++){
for (int j = 0; j < 5; j++){
if (g[i][j] == '0') {
step++;
turn(i + 1, j);
}
}
}
boolean dark = false;
// 对最后一行特判
for (int i = 0; i < 5; i++) {
if (g[4][i] == '0') {
dark = true;
break;
}
}
if (!dark) res = Math.min(res, step);
for (int i = 0; i < 5; i++) {
g[i] = backup[i].clone();
}
}
if (res > 6) res = -1;
System.out.println(res);
}
}
// 利用偏移量改变5个位置的值
private static void turn(int x, int y) {
for (int i = 0; i < 5; i++) {
int a = x + dx[i];
int b = y + dy[i];
if (a < 0 || a >= 5 || b < 0 || b >= 5) continue; // 在边界外,直接忽略即可
g[a][b] ^= 1; // 异或运算
}
}
}
AcWing 116. 飞行员兄弟
-+--
----
----
-+--
目的:将所有+
号变成-
号
假设切换一下图中圈红的位置,这个绿色的部分就会变成下图所示,它所处的行和列都会变化。
我们发现这个题是很难递推出来的,它跟上一题开关问题不一样,上一题是每一次只会有一个开关能影响灯泡,但是这题是每一个开关可以被很多个开关控制,这一个开关的状态并不会影响到其余开关的操作,因此我们不能用递推的方法来解决这道题。
本题是为了区分上一题,不要固定思想!!这道题没法用递推来解决咱们就直接暴力搜索所有方案。
思想:
枚举所有方案 0~2^16 - 1
按照该方案对所有开关进行操作
判断 => 记录方案
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
public class Main {
static final int N = 5;
static char[][] g = new char[N][N];
static char[][] backup = new char[N][N]; // 备份数组
static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
public static void main(String[] args) throws Exception {
for (int i = 0; i < 4; i++) g[i] = in.readLine().toCharArray();
List<PII> res = new ArrayList<>();
for (int op = 0; op < 1 << 16; op++) { // 1 << 16 同等于2^16
List<PII> temp = new ArrayList<>();
for (int i = 0; i < 4; i++) {
backup[i] = g[i].clone(); // 备份
}
// 进行操作
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if ((op >> get(i, j) & 1) == 1) {
temp.add(new PII(i, j));
turn\_all(i, j);
}
}
}
// 判断所有灯泡是否全亮
boolean has_closed = false;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if (g[i][j] == '+') has_closed = true;
}
}
if (has_closed == false) {
if (res.isEmpty() || res.size() > temp.size()) res = temp;
}
for (int i = 0; i < 4; i++) {
g[i] = backup[i].clone(); // 还原
}
}
System.out.println(res.size());
for (PII p : res) System.out.println((p.x + 1) + " " + (p.y + 1));
in.close();
}
private static void turn\_all(int x, int y) {
for (int i = 0; i < 4; i++) {
turn\_one(x, i);
turn\_one(i, y);
}
turn\_one(x, y);
}
private static void turn\_one(int x, int y) {
if (g[x][y] == '+') g[x][y] = '-';
else g[x][y] = '+';
}
/\*
返回矩阵中数的位数
0 1 2 3
4 5 6 7
8 9 10 11
12 13 14 15
\*/
private static int get(int x, int y) {
return 4 \* x + y;
}
static class PII {
int x;
int y;
public PII (int x, int y) {
this.x = x;
this.y = y;
}
![img](https://img-blog.csdnimg.cn/img_convert/07675cdecc5bdf73f8227397feab29c2.png)
![img](https://img-blog.csdnimg.cn/img_convert/230eb7001756e160be4f9f77c6af7337.png)
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!**
**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**
**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618668825)**
this.x = x;
this.y = y;
}
[外链图片转存中...(img-jNHaSQ30-1715887752719)]
[外链图片转存中...(img-Q05nTfHJ-1715887752720)]
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!**
**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**
**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618668825)**