版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/DADDY_HONG/article/details/81985956
#1195 : 高斯消元·一
时间限制:10000ms
单点时限:1000ms
内存限制:256MB
描述
小Ho:喂不得了啦,那边便利店的薯片半价了!
小Hi:啥?!
小Ho:那边的便利店在打折促销啊。
小Hi:走走走,赶紧去看看=v=
于是小Hi和小Ho来到了便利店。
老板为了促销,推出了组合包的形式,将不同数量的各类商品打包成一个组合,顾客可以选择组合进行购买。比如2袋薯片,1听可乐的组合只要5元,而1袋薯片,2听可乐的组合只要4元。
通过询问老板,小Hi和小Ho知道:一共有N种不同的商品和M种不同的商品组合;每一个组合的价格等于组合内商品售价之和,一个组合内同一件商品不会超过10件。
小Hi:这样算下来的话,一听可乐就是1元,而一包薯片是2元。小Ho,如果你知道所有的组合情况,你能分别算出每一件商品单独的价格么?
小Ho:当然可以了,这样的小问题怎么能难到我呢?
输入
第1行:2个正整数,N,M。表示商品的数量N,组合的数量M。1≤N≤500, N≤M≤2*N
第2..M+1行:N+1个非负整数,第i+1行第j列表示在第i个组合中,商品j的数量a[i][j]。第i+1行第N+1个数表示该组合的售价c[i]。0≤a[i][j]≤10, 0≤c[i]≤10^9
输出
若没有办法计算出每个商品单独的价格,输出"No solutions"
若可能存在多个不同的结果,输出"Many solutions"
若存在唯一可能的结果,输出N行,每行一个非负整数,第i行表示第i个商品单独的售价。数据保证如果存在唯一解,那么解一定恰好是非负整数解。
样例输入
2 2 2 1 5 1 2 4
样例输出
2 1
嘤嘤嘤,线代不好好学很惨的嘤!
高斯消元嘛,就求对角线方程组,嘛
按照提示一步步写就好辣:
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxn=520;
const int maxm=1020;
const double eps=1e-6;
int n,m;
double matrix[maxm][maxn];
int gauss()
{
int ans=1;
//处理出上三角矩阵x)//处理出对角线矩阵
for(int i=0;i<n;++i){ //<n不算最后一列//列从左往右遍历可以保证当前列左边都为0且消元不受影响
int p=i;
for(int j=i;j<m;++j){
if(fabs(matrix[j][i])>fabs(matrix[p][i]))
p=j;
}
swap(matrix[i],matrix[p]);
//以上代码进行行交换将对角线上的matrix[i][i]设为i行下绝对值最大的
//若仍然无法使matrix[i][i]不为0(秩<n的情况),存在多个解
if(fabs(matrix[i][i])<eps){
ans=-1;
continue;
}
//i行除以matrix[i][i],matrix[i][i]变为1
for(int j=i+1;j<=n;++j) //<=n算最后一列
matrix[i][j]/=matrix[i][i];
//消除第i列除第i行的数
for(int j=0;j<m;++j){
if(i!=j){
for(int k=i+1;k<=n;++k){ //<=n算最后一列
matrix[j][k]-=matrix[j][i]*matrix[i][k];
}
}
}
}
//若存在0=y的情况,无解
for(int i=0;i<m;++i){
//注意分n行前n行后的
if(fabs(matrix[i][n])>eps&&(i>=n||i<n&&fabs(matrix[i][i])<eps)){
ans=0;
return ans;
}
}
return ans;
}
int main()
{
while(~scanf("%d%d",&n,&m)){
for(int i=0;i<m;++i){
for(int j=0;j<=n;++j){
scanf("%lf",&matrix[i][j]);
}
}
int ans=gauss();
if(!ans)
printf("No solutions\n");
else if(ans==-1)
printf("Many solutions\n");
else
for(int i=0;i<n;++i)
printf("%d\n",(int)round(matrix[i][n])); //注意要四舍五入!
}
return 0;
}