数学题--高斯消元
高斯消元--给定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代码
//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原创,转载请注明出处).