数学题--高斯消元
高斯消元--给定n个多项式,以及n项的系数,求出每一个未知数的值。
【11.05】模拟赛
商品大采购
【问题描述】
终于逃出了夜爸爸的魔掌,小夜来到了一个巨大无比的超市。超市里琳琅满目的商品勾起了小夜的购买欲, 于是小夜推来n辆大型购物车··开始往里面塞东西!@#¥……塞了一车又一车……因为太呆了,小夜喜欢重复地买一些东西,而且每辆购物车里都会有n件物品。比如她在推第一辆车的时候会买熊宝宝、小saber、机器人……在推第2辆车的时候她还是会买熊宝宝、小saber、机器人,而且买这些东西的顺序一样,只是数目不同罢了……结帐的时候,售货员告诉她每辆购物车里的商品总价值x元,累加起来后小夜发现这是个天文数字。。。。她开始怀疑售货员有没有坑她。因为每辆车里商品太多,小夜不能直接看到商品的单价,她只知道第i辆购物车里第ai件商品的数目是多少。但她根本算不出那么多物品的单价,于是她想到了你……
任务:小夜给了你一张表,上面写着每辆车里各个商品的数目以及商品总价,请你帮小夜算出每件商品的单价是多少。
【输入格式】
输入文件中第一行有一个数字n代购物车数
接下来有n行,每行n+1个整数。前n个整数aij 代表第i辆辆购物车里第j件商品的数目,第n+1个整数xi 代表该辆购物车的总价值。
【输出格式】
输出文件一共有n行,每行一个整数,代表第i件物品vi的单价。
【输入样例】
2
1 1 3
1 2 5
【输出样例】
1
2
【数据范围】
对于20%的数据: 0<n<=10
对于100%的数据: 0<n<=500 0<vi<32767 0<xi<32767 0<aij<101
对于10%的数据限1s,对于另外20%的数据时限2s
这道题目经过分析可以得出这道题就是高斯消元
下面给出解决的方法:
1.将2--n的式子的通过把第一项和第一个式子同意起来,消掉每个式子的第一项。
2.将3--n的式子通过把第二项和第一个式子同意起来,消掉每个式子的第二项。
3.4........ 直到把消除只剩下一个未知数和一个常数,求出未知数的值,并代入上面的式子求出前面未知数的值。
下面给出代码
C++{因为标准读入太麻烦,所以自己在流读入编了一个处理四舍五入的函数}
#include <fstream>
#include <cstring>
using namespace std;
ifstream cin("shopping.in");
ofstream cout("shopping.out");
void print(double k)
{
int p=(int)k;
k=k*10;
int q=(int)k;
if (q%10>=8) p++;
cout<<p<<endl;
}
double f[602][602];
double a[602];
int main()
{
int n;
cin>>n;
for (int i=1;i<=n;i++)
for (int j=1;j<=n+1;j++)
cin>>f[i][j];
for (int i=1;i<=n-1;i++)
{
for (int j=i+1;j<=n;j++)
{
f[j][i]=f[j][i]/f[i][i];
for (int k=i+1;k<=n+1;k++)
f[j][k]=f[j][k]-f[i][k]*f[j][i];
}
}
a[n]=f[n][n+1]/f[n][n];
for (int i=n-1;i>0;i--)
{
double sum=0;
for (int j=n;j>=i+1;j--)
sum=sum+f[i][j]*a[j];
a[i]=(f[i][n+1]-sum)/f[i][i];
}
for (int i=1;i<=n;i++)
print(a[i]);
return 0;
}
经过我的个人验证,C++中的实数操作要比PASCAL慢很多,下面给出Pascal代码
pascal 代码
//made by lzooot
var
a:array[1..501,1..501] of real;
sum:real;
n,i,j,k:integer;
begin
assign(input,'Shopping.in');reset(input);
assign(output,'Shopping.out');rewrite(output);
readln(n);
for i:=1 to n do
for j:=1 to n+1 do
read(a[i,j]);
for k:=1 to n-1 do
begin
for i:=k+1 to n do
a[i,k]:=a[i,k]/a[k,k];
for i:=k+1 to n do
for j:=k+1 to n+1 do
a[i,j]:=a[i,j]-a[i,k]*a[k,j];
end;
for i:=n downto 1 do
begin
sum:=0;
for j:=i+1 to n do
sum:=sum+a[i,j]*a[j,n+1];
a[i,n+1]:=(a[i,n+1]-sum)/a[i,i];
end;
for i:=1 to n do
writeln(a[i,n+1]:0:0);
close(input);close(output);
end.
本文地址:http://www.cnblogs.com/foreverzsz/archive/2010/11/06/1870588.html
(foreverzsz原创,转载请注明出处).
