POJ 1830 开关问题 高斯消元,自由变量个数
http://poj.org/problem?id=1830
如果开关s1操作一次,则会有s1(记住自己也会变)、和s1连接的开关都会做一次操作。
那么设矩阵a[i][j]表示按下了开关j,开关i会被操作一次,记得a[i][i] = 1是必须的,因为开关i操作一次,本身肯定会变化一次。
所以有n个开关,就有n条方程,
每个开关的操作次数总和是:a[i][1] + a[i][2] + ... + a[i][n]
那么sum % 2就代表它的状态,需要和(en[i] - be[i] + 2) % 2相等。就是操作次数的奇偶性要相等。
那么来一个高斯消元,就知道是否有可能有解。
在有解的情况下,可能存在自由变量,什么意思呢?
就是假设有k个自由变量,那么就是前n - k个变量有固定的操作,使得能变成最终结果,那么这k个自由变量就可以任取值了,一共有2^k种不同的取值方案。因为方案不要求有顺序,所以那个灯取那个状态,都是相同的一种解。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <assert.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL; #include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <bitset>
const int maxn = 1e2 + ;
class GaussMatrix { //复杂度O(n3)
public:
int a[maxn][maxn];
int equ, val; //方程(行)个数,和变量(列)个数,其中第val个是b值,不能取
void init() {
for (int i = ; i <= equ; ++i) {
for (int j = ; j <= val; ++j) {
a[i][j] = ;
}
}
}
void swapRow(int rowOne, int rowTwo) {
for (int i = ; i <= val; ++i) {
swap(a[rowOne][i], a[rowTwo][i]);
}
}
void swapCol(int colOne, int colTwo) {
for (int i = ; i <= equ; ++i) {
swap(a[i][colOne], a[i][colTwo]);
}
}
// bool same(double x, double y) {
// return fabs(x - y) < eps;
// }
int guass() {
int k, col; // col,当前要处理的列, k当前处理的行
for (k = , col = ; k <= equ && col < val; ++k, ++col) { //col不能取到第val个
int maxRow = k; //选出列最大值所在的行,这样使得误差最小。(没懂)
for (int i = k + ; i <= equ; ++i) {
if (abs(a[i][col]) > abs(a[maxRow][col])) {
maxRow = i;
}
}
if (a[maxRow][col] == ) { //如果在第k行以后,整一列都是0
--k; //则这个变量就是一个自由变量。
continue;
}
if (maxRow != k) swapRow(k, maxRow); // k是当前的最大行了
for (int i = col + ; i <= val; ++i) { //整一列约去系数
a[k][i] /= a[k][col];
}
a[k][col] = ; //第一个就要变成1了,然后它下面和上面的变成0
for (int i = ; i <= equ; ++i) {
if (i == k) continue; //当前这行,不操作
for (int j = col + ; j <= val; ++j) {
a[i][j] = (a[i][j] - a[i][col] * a[k][j] + ) % ;
}
a[i][col] = ;
}
// debug();
}
for (int res = k; res <= equ; ++res) {
if (a[res][val] != ) return -; //方程无解
}
return val - k; //自由变量个数
}
void debug() {
for (int i = ; i <= equ; ++i) {
for (int j = ; j <= val; ++j) {
cout << a[i][j] << " ";
}
printf("\n");
}
printf("*******************************************\n\n");
}
}arr;
int be[maxn], en[maxn];
void work() {
int n;
cin >> n;
for (int i = ; i <= n; ++i) cin >> be[i];
for (int i = ; i <= n; ++i) cin >> en[i];
arr.init();
// memset(&arr, 0, sizeof arr);
arr.equ = n, arr.val = n + ;
do {
int x, y;
cin >> x >> y;
if (x == && y == ) break;
arr.a[x][x] = ;
arr.a[y][x] = ;
} while (true);
for (int i = ; i <= n; ++i) {
arr.a[i][n + ] = (en[i] - be[i] + ) % ;
arr.a[i][i] = ; //这个是必须的。
}
// arr.debug();
int res = arr.guass();
if (res == -) {
cout << "Oh,it's impossible~!!" << endl;
} else cout << ( << res) << endl;
} int main() {
#ifdef local
freopen("data.txt", "r", stdin);
// freopen("data.txt", "w", stdout);
#endif
int t;
cin >> t;
while (t--) work();
return ;
}
POJ 1830 开关问题 高斯消元,自由变量个数的更多相关文章
- POJ 1830 开关问题 (高斯消元)
题目链接 题意:中文题,和上篇博客POJ 1222是一类题. 题解:如果有解,解的个数便是2^(自由变元个数),因为每个变元都有两种选择. 代码: #include <iostream> ...
- POJ 1830 开关问题 [高斯消元XOR]
和上两题一样 Input 输入第一行有一个数K,表示以下有K组测试数据. 每组测试数据的格式如下: 第一行 一个数N(0 < N < 29) 第二行 N个0或者1的数,表示开始时N个开关状 ...
- POJ.1830.开关问题(高斯消元 异或方程组)
题目链接 显然我们需要使每个i满足\[( ∑_{j} X[j]*A[i][j] ) mod\ 2 = B[i]\] 求这个方程自由元Xi的个数ans,那么方案数便是\(2^{ans}\) %2可以用^ ...
- POJ 3185 The Water Bowls 【一维开关问题 高斯消元】
任意门:http://poj.org/problem?id=3185 The Water Bowls Time Limit: 1000MS Memory Limit: 65536K Total S ...
- POJ - 1681: Painter's Problem (开关问题-高斯消元)
pro:开关问题,同上一题. 不过只要求输出最小的操作步数,无法完成输出“inf” sol:高斯消元的解对应的一组合法的最小操作步数. #include<bits/stdc++.h> #d ...
- POJ - 1222: EXTENDED LIGHTS OUT (开关问题-高斯消元)
pro:给定5*6的灯的状态,如果我们按下一个灯的开关,它和周围4个都会改变状态.求一种合法状态,使得终状态全为关闭: sol:模2意义下的高斯消元. 终于自己手打了一个初级板子. #include& ...
- A - The Water Bowls POJ - 3185 (bfs||高斯消元)
题目链接:https://vjudge.net/contest/276374#problem/A 题目大意:给你20个杯子,每一次操作,假设当前是对第i个位置进行操作,那么第i个位置,第i+1个位置, ...
- POJ 1166 The Clocks 高斯消元 + exgcd(纯属瞎搞)
依据题意可构造出方程组.方程组的每一个方程格式均为:C1*x1 + C2*x2 + ...... + C9*x9 = sum + 4*ki; 高斯消元构造上三角矩阵,以最后一个一行为例: C*x9 = ...
- POJ 2065 SETI(高斯消元)
题目链接:http://poj.org/problem?id=2065 题意:给出一个字符串S[1,n],字母a-z代表1到26,*代表0.我们用数组C[i]表示S[i]经过该变换得到的数字.给出一个 ...
随机推荐
- 关于VLOOKUP函数的用法
“Lookup”的汉语意思是“查找”,在Excel中与“Lookup”相关的函数有三个:VLOOKUP.HLOOKUO和LOOKUP.下面介绍VLOOKUP函数的用法. 一.功能 在表格的首列查找指定 ...
- codeforces B. Ciel and Flowers 解题报告
题目链接:http://codeforces.com/problemset/problem/322/B 题目意思:给定红花.绿花和蓝花的朵数,问组成四种花束(3朵红花,3朵绿花,3朵蓝花,1朵红花+1 ...
- 为什么要把页面放在 WEB-INF 路径下?
1.基于不同的功能 JSP 被放置在不同的目录下 这种方法的问题是这些页面文件容易被偷看到源代码,或被直接调用.某些场合下这可能不是个大问题,可是在特定情形中却可能构成安全隐患.用户可以绕过Strut ...
- JavaWeb学习总结(三)response与request
一.response response是Servlet.service方法的一个参数,类型为javax.servlet.http.HttpServletResponse.在客户端发出每个请求时,服务器 ...
- 【C/C++】函数指针
首先必须要清楚如下: [1]函数指针即函数的地址,也就是存储其机器语言代码的首地址.该地址用函数名表示. [2]用具体的函数名给函数指针变量赋值时必须满足两者的类型(即函数返回值类型)和特征标(即函数 ...
- 4.13 BJ集训
T1 Mobitel 题目大意: 一个全是正整数的矩阵,求从左上角到右下角的简单路径有多少条路径上数的乘积$>=K$ 思路: 由于整数分块,我们设$f(i,j,k)$表示走到$(i,j)$,$k ...
- Linux wpa_cli 调试方法
记录一下如何使用wpa_cli来进行wifi调试. 1.启动WLAN (1)加载驱动 打开wifi的时候会加载驱动,关闭则会卸载wifi驱动.手动调试的时候,先调用insmod/rmmod命令加载/ ...
- weex 打包apk
安装 weexpack weexpack create my-project //创建项目 cd my-project cnpm install //安装依赖 npm start //运行项目 ...
- saltstack master minion安装配置简单使用
首先先了解下saltstack是什么,为什么使用它 它与Ansible.Puppet都属于集中管理工具,由于现在企业规模的不断庞大及业务的增长,所需要管理的服务器数量增多,而且大部分机器都属于同类业务 ...
- CS231n 2016 通关 第五章 Training NN Part1
在上一次总结中,总结了NN的基本结构. 接下来的几次课,对一些具体细节进行讲解. 比如激活函数.参数初始化.参数更新等等. ====================================== ...