SOJ 1048.Inverso

解题技巧:

  1.将3*3矩阵的状态压缩成一个整数来表示,使用二进制位运算来进行状态转移。

  2.使用广度优先搜索求最短路径,从1-9种状态转移进行尝试,保证第一次得到的答案是字典序最小的。

  3.如果题目给出的状态为目标状态,也就是wwwwwwwww,则应该输出11(表示先按1位置一次,再按1位置一次)。

代码如下:

 1 #include <iostream>
 2 #include <string>
 3 #include <queue>
 4 #include <stack>
 5 #include <vector>
 6 using namespace std;
 7
 8 // 一个代表区域状态的整数的二进制表示中,0表示白色,1表示黑色.
 9
10 const int STATES = 1 << 9;
11 bool visited[STATES];
12
13 struct Elem {
14     int state;
15     int previous;
16     int op_num;
17     Elem(int s = 0, int p = 0, int on = 0) : state(s), previous(p), op_num(on) {}
18 };
19
20 int goal = 0;   // 目标状态,1-9全为白色.
21
22 vector<Elem> elems;
23 // Clicking field 1 inverts fields 1, 2, 4, 5
24 // Clicking field 2 inverts fields 1, 2, 3, 4, 5, 6
25 // Clicking field 3 inverts fields 2, 3, 5, 6
26 // Clicking 4 inverts fields 1, 2, 4, 5, 7, 8
27 // Clicking 5 inverts fields all fields
28 // Clicking 6 inverts fields 2, 3, 5, 6, 8, 9
29 // Clicking 7 inverts fields 4, 5, 7, 8
30 // Clicking 8 inverts fields 4, 5, 6, 7, 8, 9
31 // Clicking 9 inverts fields 5, 6, 8, 9
32 int click[10] = { 0, 27, 63, 54, 219, 511, 438, 216, 504, 432};
33
34 void init() {
35     elems.clear();
36     for (int i = 0; i < STATES; ++i) visited[i] = false;
37 }
38
39 int main() {
40     int n; cin >> n;
41     while (n--) {
42         string s; cin >> s; init();
43         elems.push_back(Elem()); Elem &elem = elems.back();
44         for (int i = 0; i < s.size(); ++i) {
45             if (s[i] == ‘b‘) {
46                 elem.state += 1 << i;
47             }
48         }
49         elem.previous = elem.op_num = -1;
50         if (elem.state != goal) visited[elem.state] = true;
51         int left = 0, right = 1;
52         bool find = false;
53         while (left < right && !find) {
54             for (int i = 1; i <= 9 && !find; ++i) {
55                 Elem &e = elems[left];
56                 Elem next_e;
57                 next_e.state = e.state ^ click[i];
58                 next_e.previous = left;
59                 next_e.op_num = i;
60                 if (!visited[next_e.state]) {
61                     visited[next_e.state] = true;
62                     elems.push_back(next_e); ++right;
63                 }
64                 if (next_e.state == goal) {
65                     find = true;
66                 }
67             }
68             ++left;
69         }
70         stack<int> st;
71         int cur = right - 1;
72         while (cur != 0) {
73             st.push(elems[cur].op_num);
74             cur = elems[cur].previous;
75         }
76         while (!st.empty()) {
77             cout << st.top(); st.pop();
78         }
79         cout << endl;
80     }
81
82     return 0;
83 }
时间: 2024-08-03 17:32:10

SOJ 1048.Inverso的相关文章

编程题目分类(剪辑)

1. 编程入门 2. 数据结构 3. 字符串 4. 排序 5. 图遍历 6. 图算法 7. 搜索:剪枝,启发式搜索 8. 动态规划/递推 9. 分治/递归 10. 贪心 11. 模拟 12. 算术与代数 13. 组合问题 14. 数论 15. 网格,几何,计算几何 [编程入门] PC 110101, uva 100, The 3n+1 problem, 难度 1 PC 110102, uva 10189, Minesweeper, 难度 1 PC 110103, uva 10137, The T

(转)sicily题目分类

Sicily题目分类 ·         [数据结构/图论] 1310 Right-Heavy Tree   笛卡尔树相关,复杂度O(N)或O(NlogN). ·1426 Phone List         电话号码前缀检索,trie树相关. ·1443 Printer Queue      基本队列操作. ·1149 等价表达式         判断表达式是否等价(递归求解) ·1136 山海经             n长序列里求m次区间询问的最大连续子区间和.线段树/RMQ ·1252

1048: 导弹防御系统

1048: 导弹防御系统 时间限制: 1 Sec  内存限制: 128 MB提交: 836  解决: 349[提交][状态][讨论版] 题目描述 某国为了防御敌国的导弹袭击,开发出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度.某天,雷达捕捉到敌国的导弹来袭,并观测到导弹依次飞来的高度,请计算这套系统最多能拦截多少导弹.拦截来袭导弹时,必须按来袭导弹袭击的时间顺序,不允许先拦截后面的导弹,再拦截前面的导弹. 输入

UVA 1048 - Low Cost Air Travel(最短路)

UVA 1048 - Low Cost Air Travel 题目链接 题意:给定一些联票,在给定一些行程,要求这些行程的最小代价 思路:最短路,一张联票对应几个城市就拆成多少条边,结点表示的是当前完成形成i,在城市j的状态,这样去进行最短路,注意这题有坑点,就是城市编号可能很大,所以进行各种hash 代码: #include <cstdio> #include <cstring> #include <vector> #include <queue> #in

SOJ 4445 2015四川省赛模拟题

背景:赛场上就是因为没开这道题,而没拿到银,回来A了,感觉代码能力还是很弱,一定要先想好再敲,而且注重代码的函数化,这样无论是观感,还是调试都要好很多,逻辑要清晰,看代码要仔细,提交之前通读代码. 题意:起点在原点的frog,开始向右运动,且碰到障碍物就右转,问转多少次? 思路:关键是图的大小范围是109,无法存下,只有用类似链表的方法来存图.这里用了两个容器,一个以X为基准,一个一Y为基准,这两个容器设置很特殊,是为了满足题中特殊的查询需要:查询前进方向最近障碍物. 我的代码: #includ

The Hardest Problem Ever(杭电1048)

/*The Hardest Problem Ever Problem Description Julius Caesar lived in a time of danger and intrigue. The hardest situation Caesar ever faced was keeping himself alive. In order for him to survive, he decided to create one of the first ciphers. This c

HDU 1048 What Is Your Grade? (简单模拟)

 What Is Your Grade? Problem Description "Point, point, life of student!" This is a ballad(歌谣)well known in colleges, and you must care about your score in this exam too. How many points can you get? Now, I told you the rules which are used in

1048 石子归并

1048 石子归并 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 有n堆石子排成一列,每堆石子有一个重量w[i], 每次合并可以合并相邻的两堆石子,一次合并的代价为两堆石子的重量和w[i]+w[i+1].问安排怎样的合并顺序,能够使得总合并代价达到最小. 输入描述 Input Description 第一行一个整数n(n<=100) 第二行n个整数w1,w2...wn  (wi <= 100) 输出描述 Output Des

九度oj 题目1048:判断三角形类型

题目1048:判断三角形类型 时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:8240 解决:3992 题目描述: 给定三角形的三条边,a,b,c.判断该三角形类型. 输入: 测试数据有多组,每组输入三角形的三条边. 输出: 对于每组输入,输出直角三角形.锐角三角形.或是钝角三角形. 样例输入: 3 4 5 样例输出: 直角三角形 1 #include <iostream> 2 #include <algorithm> 3 using namespace std; 4 i