高斯消元几道入门题总结POJ1222&&POJ1681&&POJ1830&&POJ2065&&POJ3185
最近在搞高斯消元,反正这些题要么是我击败了它们,要么就是这些题把我给击败了。现在高斯消元专题部分还有很多题,先把几道很简单的入门题总结一下吧。
专题:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=29538#overview
专题地址来源于kuangbin大神,多谢kuangbin大神总结的高斯消元的模板,菜鸟在此谢过啊。
POJ1222:http://poj.org/problem?id=1222
题意是有5行六列30个开关,然后每拨动一个开关就会影响到其相邻的开关的状态。给了一个初始01的状态,问最终能否所有的值都为1。
一开始对这个高斯消元真的是相当地难以理解,要把这30个开关想象成是30个方程,第i个开关状态对应于第i个方程的右边的值。左边的是所有能够影响到的开关的值。我自己一开始这块真的很难理解,直到跑了几次程序才弄懂。然后就是高斯消元求解。其实高斯消元解方程本身的原理并不难,但就像图论题一样的,难在于建立方程,并且方程本身有各种幺蛾子,比方说我现在面对的POJ1487。。。跑题了。。。
代码:
#pragma warning(disable:4996)
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <string>
#include <cstring>
using namespace std; int res[35];
int val[35][35];
int templat[35][35]; void Gauss()
{
int row, col, i, j, k; for (row = 1, col = 1; col <= 30 && row <= 30; col++, row++)
{
k = row;
while (val[k][col] == 0 && k <= 30)
k++; if (k != row)
{
for (i = 1; i <= 31; i++)
{
swap(val[k][i], val[row][i]);
}
}
for (i = row + 1; i <= 30; i++)
{
if (val[i][col])
{
for (j = col; j <= 31; j++)
{
val[i][j] = val[i][j] ^ val[row][j];
}
}
}
} for (i = 30; i >= 1; i--)
{
res[i] = val[i][31];
for (j = 30; j > i; j--)
{
res[i] ^= (val[i][j] && res[j]);
}
}
} int main()
{
//freopen("i.txt", "r", stdin);
//freopen("o.txt", "w", stdout); int t, test, i, j, k;
memset(templat, 0, sizeof(templat)); for (i = 0; i < 5; i++)
{
for (j = 1; j <= 6; j++)
{
templat[i * 6 + j][i * 6 + j] = 1;
if (i - 1 >= 0)
{
templat[i * 6 + j][(i - 1) * 6 + j] = 1;
}
if (i + 1 < 5)
{
templat[i * 6 + j][(i + 1) * 6 + j] = 1;
}
if (j - 1 >= 1)
{
templat[i * 6 + j][i * 6 + j - 1] = 1;
}
if (j + 1 <= 6)
{
templat[i * 6 + j][i * 6 + j + 1] = 1;
}
}
} scanf("%d", &t);
for (test = 1; test <= t; test++)
{
printf("PUZZLE #%d\n", test);
memcpy(val, templat, sizeof(templat));
memset(res, 0, sizeof(res)); for (i = 0; i < 5; i++)
{
for (j = 1; j <= 6; j++)
{
scanf("%d", &val[i * 6 + j][31]);
}
}
Gauss(); for (i = 1; i <= 30; i++)
{
if (i % 6 == 1)
{
printf("%d", res[i]);
}
else
{
printf(" %d", res[i]);
}
if (i % 6 == 0)
{
printf("\n");
}
}
} //system("pause");
return 0;
}
POJ1681:http://poj.org/problem?id=1681
和POJ1222一样的题意,理解POJ1222这个题也就好理解了,求出每一个点的值,查1的个数。
代码:
#pragma warning(disable:4996)
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <string>
#include <cstring>
using namespace std; int dir[5][2] = {
{0,0},
{-1,0},
{1,0},
{0,-1},
{0,1}
}; int n;
int x[300];
char val_c[300][300];
int val[300][300]; int Gauss()
{
int row, col, i, j, k, ans; ans = 0;
for (row = 1, col = 1; col <= n&&row <= n; col++, row++)
{
k = row;
while (val[k][col] == 0 && k <= n)
k++;
if (k>n)
{
row--;
ans++;
continue;
}
if (k != row)
{
for (j = 1; j <= n + 1; j++)
{
swap(val[k][j], val[row][j]);
}
}
for (i = row + 1; i <= n; i++)
{
if (val[i][col])
{
for (j = col; j <= n + 1; j++)
{
val[i][j] = val[i][j] ^ val[row][j];
}
}
}
}
for (i = row; i <= n; i++)
{
if (val[i][n + 1])
return -1;
}
for (i = n - ans; i >= 1; i--)
{
x[i] = val[i][n + 1];
for (j = n; j > i; j--)
{
x[i] ^= (val[i][j] && x[j]);
}
}
ans = 0;
for (i = 1; i <= n; i++)
{
if (x[i])
ans++;
}
return ans;
} int main()
{
//freopen("i.txt", "r", stdin);
//freopen("o.txt", "w", stdout); int a, b, ans;
int t, i, j, k; scanf("%d", &t); while (t--)
{
scanf("%d", &n); memset(val, 0, sizeof(val));
memset(val_c, 0, sizeof(val_c));
memset(x, 0, sizeof(x)); for (i = 1; i <= n; i++)
{
for (j = 1; j <= n; j++)
{
for (k = 0; k <= 4; k++)
{
a = i + dir[k][0];
b = j + dir[k][1];
if (a >= 1 && a <= n&&b >= 1 && b <= n)
{
val[(i - 1)*n + j][(a - 1)*n + b] = 1;
}
}
}
}
for (i = 1; i <= n; i++)
{
cin >> val_c[i] + 1;
for (j = 1; j <= n; j++)
{
if (val_c[i][j] == 'w')
{
val[(i - 1)*n + j][n*n + 1] = 1;
}
}
}
n = n*n;
ans = Gauss();
if (ans == -1)
{
printf("inf\n");
}
else
{
printf("%d\n",ans);
}
}
//system("pause");
return 0;
}
POJ1830:http://poj.org/problem?id=1830
判断多解、无解的情况。另外这个题目一定要注意i、j的顺序,如果j的开关影响到了i,那么应该是在i的方程里面出现j,所以是val[i][j]=1。放到题目当中,两者顺序要调换!!!
代码:
#pragma warning(disable:4996)
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <string>
#include <cstring>
using namespace std; int n;
int s[350], e[350], x[350], x2[350];
int res[350][350], res2[350][350]; int Gauss()
{
int row, col, i, j, k, ans; ans = 0;
for (row = 1, col = 1; col <= n&&row <= n; col++, row++)
{
k = row;
while (res[k][col] == 0 && k <= n)
k++;
if (k>n)
{
row--;
ans++;
continue;
}
if (k != row)
{
for (j = 1; j <= n + 1; j++)
{
swap(res[k][j], res[row][j]);
}
}
for (i = row + 1; i <= n; i++)
{
if (res[i][col])
{
for (j = col; j <= n + 1; j++)
{
res[i][j] = res[i][j] ^ res[row][j];
}
}
}
}
for (i = row; i <= n; i++)
{
if (res[i][n + 1])
return -1;
}
if (row <= n)
return (1 << (n - row+1));
else
return 1;
} int main()
{
//freopen("i.txt", "r", stdin);
//freopen("o.txt", "w", stdout); int k, i, j, ans;
scanf("%d", &k); while (k--)
{
scanf("%d", &n); memset(res, 0, sizeof(res));
memset(res2, 0, sizeof(res2));
memset(x, 0, sizeof(x));
memset(x2, 0, sizeof(x2));
memset(e, 0, sizeof(e));
memset(s, 0, sizeof(s));
for (i = 1; i <= n; i++)
{
scanf("%d", &s[i]);
res[i][i] = 1;
} for (i = 1; i <= n; i++)
{
scanf("%d", &e[i]);
res[i][n + 1] = s[i] ^ e[i];
}
for (;;)
{
scanf("%d%d", &i, &j);
if (i == 0 && j == 0)
break;
res[j][i] = 1;
}
memcpy(res2, res, sizeof(res));
ans = Gauss();
if (ans == -1)
{
printf("Oh,it's impossible~!!\n");
}
else
{
printf("%d\n", ans);
}
}
//system("pause");
return 0;
}
POJ2065:http://poj.org/problem?id=2065
题意实在是。。。直接理解成来了一个质数p和一个字符串,这个字符串的长度决定了有多少个方程,每个方程的右边的值是相应的字符的值,a对应0,b对应1。。。z对应26,*对应0。
第i个方程左边第j个变量的系数是pow(i,j)mod p,直接求解。
代码:
#pragma warning(disable:4996)
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <string>
#include <cstring>
using namespace std; int p;
char res[75];
int x[305];//解集
int val[305][305];//增广矩阵
bool free_x[305];//标记是否是不确定的变元 inline int gcd(int a, int b)
{
int t;
while (b != 0)
{
t = b;
b = a%b;
a = t;
}
return a;
} inline int lcm(int a, int b)
{
return a / gcd(a, b)*b;//先除后乘防溢出
} int Gauss(int equ, int var)
{
int i, j, k;
int max_r;//当前这列绝对值最大的行
int col;//当前处理的列
int ta, tb;
int LCM;
int temp;
int free_x_num;
int free_index; for (int i = 0; i <= var; i++)
{
x[i] = 0;
free_x[i] = true;
}
//转换为阶梯阵
col = 0;//当前处理的列
for (k = 0; k < equ&&col < var; k++, col++)
{
//枚举当前处理的行
//找到该col列元素绝对值最大的那行与第k行交换.(为了在除法时减少误差)
max_r = k;
for (i = k + 1; i < equ; i++)
{
if (abs(val[i][col])>abs(val[max_r][col]))
max_r = i;
}
if (max_r != k)
{//与第k行交换
for (j = k; j < var + 1; j++)
swap(val[k][j], val[max_r][j]);
}
if (val[k][col] == 0)
{
k--;
continue;
}
for (i = k + 1; i < equ; i++)
{//枚举要删去的行
if (val[i][col] != 0)
{
LCM = lcm(abs(val[i][col]), abs(val[k][col]));
ta = LCM / abs(val[i][col]);
tb = LCM / abs(val[k][col]);
if (val[i][col] * val[k][col] < 0)
tb = -tb;
for (j = col; j < var + 1; j++)
{
val[i][j] = ((val[i][j] * ta - val[k][j] * tb) % p + p) % p;
}
}
}
}
for (i = var - 1; i >= 0; i--)
{
temp = val[i][var];
for (j = i + 1; j < var; j++)
{
if (val[i][j] != 0)
{
temp = temp - val[i][j] * x[j];
temp = (temp % p + p) % p;
}
}
while ((temp % val[i][i]))temp += p;
x[i] = ((temp / val[i][i]) % p + p) % p;
}
return 0;
} int getresult(int A, int n, int k)
{
int b = 1;
while (n > 0)
{
if (n & 1)
{
b = (b*A) % k;
}
n = n >> 1;
A = (A*A) % k;
}
return b;
} int main()
{
//freopen("i.txt", "r", stdin);
//freopen("o.txt", "w", stdout); int test, i, j, len;
scanf("%d", &test); while (test--)
{
memset(val, 0, sizeof(val)); scanf("%d%s", &p, res); len = strlen(res);
for (i = 0; i < len; i++)
{
if (res[i] == '*')
val[i][len] = 0;
else
val[i][len] = res[i] - 'a' + 1; for (j = 0; j < len; j++)
val[i][j] = getresult(i + 1, j, p);
}
Gauss(len, len);
for (i = 0; i < len; i++)
{
if (i == 0)
printf("%d", x[i]);
else
printf(" %d", x[i]);
}
printf("\n");
} //system("pause");
return 0;
}
POJ3185:http://poj.org/problem?id=3185
之前的好歹是个二维的,这次的这个是一维的,每个bowl翻过来影响到周围的两个,没有用高斯消元。。。太麻烦了,直接贪心。
代码:
#pragma warning(disable:4996)
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <string>
#include <cstring>
using namespace std; int minn;
int val[25];
int val_c[25]; void dfs1(int i, int a[],int num)
{
if (i == 22)
{
minn = min(minn, num);
return;
}
if (a[i - 1] == 1)
{
a[i - 1] = (a[i - 1] + 1) & 1;
a[i] = (a[i] + 1) & 1;
a[i + 1] = (a[i + 1] + 1) & 1;
dfs1(i + 1, a, num + 1); a[i - 1] = (a[i - 1] + 1) & 1;
a[i] = (a[i] + 1) & 1;
a[i + 1] = (a[i + 1] + 1) & 1;
}
else
{
dfs1(i + 1, a, num);
}
} void dfs2(int i, int a[], int num)
{
if (i == -1)
{
minn = min(minn, num);
return;
}
if (a[i + 1] == 1)
{
a[i + 1] = (a[i + 1] + 1) & 1;
a[i] = (a[i] + 1) & 1;
a[i - 1] = (a[i - 1] + 1) & 1;
dfs2(i - 1, a, num + 1);
a[i + 1] = (a[i + 1] + 1) & 1;
a[i] = (a[i] + 1) & 1;
a[i - 1] = (a[i - 1] + 1) & 1;
}
else
{
dfs2(i - 1, a, num);
}
} int main()
{
//freopen("i.txt", "r", stdin);
//freopen("o.txt", "w", stdout); int i; memset(val, 0, sizeof(val));
for (i = 1; i <= 20; i++)
scanf("%d", val + i); minn = 200;
dfs1(2,val,0);
dfs2(19, val, 0);
cout << minn << endl;
//system("pause");
return 0;
}
高斯消元几道入门题总结POJ1222&&POJ1681&&POJ1830&&POJ2065&&POJ3185的更多相关文章
- 期望dp+高斯消元优化——uvalive4297好题
非常好的题!期望+建矩阵是简单的,但是直接套高斯消元会T 所以消元时要按照矩阵的形态 进行优化 #include<bits/stdc++.h> using namespace std; ; ...
- SPOJ HIGH(生成树计数,高斯消元求行列式)
HIGH - Highways no tags In some countries building highways takes a lot of time... Maybe that's bec ...
- hdu 3359 Kind of a Blur (高斯消元 浮点型)
题目链接 题意: H * W (W,H <= 10) 的矩阵A的某个元素A[i][j],从它出发到其他点的曼哈顿距离小于等于D的所有值的和S[i][j]除上可达点的数目,构成了矩阵B.给定矩阵B ...
- [BZOJ 4820] [SDOI2017] 硬币游戏(高斯消元+概率论+字符串hash)
[BZOJ 4820] [SDOI2017] 硬币游戏(高斯消元+概率论+字符串hash) 题面 扔很多次硬币后,用H表示正面朝上,用T表示反面朝上,会得到一个硬币序列.比如HTT表示第一次正面朝上, ...
- 2014多校第一场J题 || HDU 4870 Rating(DP || 高斯消元)
题目链接 题意 :小女孩注册了两个比赛的帐号,初始分值都为0,每做一次比赛如果排名在前两百名,rating涨50,否则降100,告诉你她每次比赛在前两百名的概率p,如果她每次做题都用两个账号中分数低的 ...
- HDU 4818 RP problem (高斯消元, 2013年长春区域赛F题)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4818 深深地补一个坑~~~ 现场赛坑在这题了,TAT.... 今天把代码改了下,过掉了,TAT 很明显 ...
- 2017湘潭赛 A题 Determinant (高斯消元取模)
链接 http://202.197.224.59/OnlineJudge2/index.php/Problem/read/id/1260 今年湘潭的A题 题意不难 大意是把n*(n+1)矩阵去掉某一列 ...
- 【BZOJ 1013】【JSOI2008】球形空间产生器sphere 高斯消元基础题
最基础的高斯消元了,然而我把j打成i连WA连跪,考场上再犯这种错误就真的得滚粗了. #include<cmath> #include<cstdio> #include<c ...
- 【XSY3154】入门多项式 高斯消元
题目大意 给你一个 \(n\times n\)的矩阵 \(A\),求次数最小且最高次项为 \(1\) 的多项式 \(F(x)\),满足 \(F(A)=0\). 所有操作都对 \(p\) 取模. \(n ...
随机推荐
- Windows配置本地Hadoop运行环境
很多人喜欢用Windows本地开发Hadoop程序,这里是一个在Windows下配置Hadoop的教程. 首先去官网下载hadoop,这里需要下载一个工具winutils,这个工具是编译hadoop用 ...
- java 责任链模式的三种实现
责任链模式 责任链模式的定义:使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系, 将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理他为止.这里就不再过多的介绍什么 ...
- 如果谷歌浏览器突然打不开网页,而且显示:"网页可能暂时无法连接,或者它已永久性地移动到了新网址,返回ERR_TUNNEL_CONNECTION_FAILED",怎么办?用这个方法,亲试有效!!!
打开cmd: 依次输入: ipconfig /flushdnsnbtstat –rnetsh int ip resetnetsh winsock reset 效果图 然后我的浏览器就能正常使用了,很有 ...
- 【Hibernate 多对多】
HibernateManytoMany public class HibernateManytoMany { //演示维护第三张表 @Test public void testTable2() { S ...
- 添加COOKIE
HttpCookie userinfoCookie = new HttpCookie("userinfo"); JObject o = new JObject();//JObjec ...
- js判断ie和edge是否安装Adobe Reader PDF阅读器
ie浏览器和edge浏览器,必须用Adobe Reader PDF阅读器才可以打开pdf文件,其他现代浏览器自带pdf阅读器,无需安装. 判断ie或者edge如果安装了,就浏览pdf文件:如果没安装就 ...
- RestTemplate post请求使用map传参 Controller 接收不到值的解决方案 postForObject方法源码解析.md
结论 post方法中如果使用map传参,需要使用MultiValueMap来传递 RestTemplate 的 postForObject 方法有四个参数 String url => 顾名思义 ...
- 【摘录自MDN】预定义函数
JavaScript语言有好些个顶级的内建函数: eval() eval()方法会对一串字符串形式的JavaScript代码字符求值. uneval() uneval()方法创建的一个Object的 ...
- Java自学-集合框架 ArrayList和LinkedList的区别
ArrayList和LinkedList的区别 步骤 1 : ArrayList和LinkedList的区别 ArrayList ,插入,删除数据慢 LinkedList, 插入,删除数据快 Arra ...
- input输入文字的时候背景会变色,如何去掉呢?
默认,如图: 当input框输入文字的时候背景会变色,如图: 有两种方法: 1.在form标签里家这个属性就行: autocomplete="off"