6-3 There is No Free Lunch (40分)

One day, CYLL found an interesting piece of commercial from newspaper: the Cyber-restaurant was offering a kind of “Lunch Special” which was said that one could “buy one get two for free”. That is, if you buy one of the dishes on their menu, denoted by d​i
​​ with price pi, you may get the two neighboring dishes di−1 and di+1 for free! If you pick up d1, then you may get d2and the last one d​n for free, and if you choose the last one d​n​​ , you may get d​n−1​​ and d​1​​ for free.

However, after investigation CYLL realized that there was no free lunch at all. The price p​i
​​ of the i-th dish was actually calculated by adding up twice the cost c​i
​​ of the dish and half of the costs of the two “free” dishes. Now given all the prices on the menu, you are asked to help CYLL find the cost of each of the dishes.

Format of function:
void Price( int n, double p[] );
where int n satisfies that 2< n ≤10000; double p[] is passed into the function as an array of prices p​,i and then will be returned storing the costs of the dishes.

Sample program of judge:

#include <stdio.h>

#define Max_size 10000 /* max number of dishes */

void Price( int n, double p[] );

int main()
{
    int n, i;
    double p[Max_size];

    scanf("%d", &n);
    for (i=0; i<n; i++) 
        scanf("%lf", &p[i]);
    Price(n, p);
    for (i=0; i<n; i++)
        printf("%.2f ", p[i]);
    printf("\n");

    return 0;
}

/* Your function will be put here */

Sample Input:
12 23.64 17.39 12.77 16.62 10.67 14.85 12.68 26.90 28.30 15.59 37.99 23.18
Sample Output:
9.20 5.58 3.24 7.00 1.99 6.36 2.25 10.01 11.52 0.50 17.65 4.88

尝试的方法:

高斯法:只能过前两个点,原因是内存不允许定义double * 10001 * 10001的数组

追赶法(?):查了才知道有这个怪异的名字。主要想法就是 x 2 x_2 x2,… x n − 1 x_{n-1} xn1都用 x 1 x_1 x1 x n x_n xn表示,然后带到最后一个方程里解。
只能过前两个点,原因是随着迭代次数增加, x 1 x_1 x1, x n x_n xn的系数和常数项都会变的很大,超出double范围。(主要是因为这个矩阵的元素都是正的)

参数法+LU分解:
解法:
求解: [ 2 0.5 0 . . . 0 0 0.5 0.5 2 0.5 . . . 0 0 0 . . . . . . . . . . . . . . . . . . . . . . . . . . . 0.5 2 0.5 . . . . . . . . . . . . . . . . . . . . . . . . . . . 0 0 0 . . . 0.5 2 0.5 0.5 0 0 . . . 0 0.5 2 ] [ x 1 x 2 x 3 . . . . . . . . . x n ] = [ p 1 p 2 p 3 . . . . . . . . . p n ] \begin{bmatrix}2&0.5&0&...&0&0&0.5\\\\0.5&2&0.5&...&0&0&0\\\\...&...&...&...&...&...&...\\\\...&...&0.5&2&0.5&...&...\\\\...&...&...&...&...&...&...\\\\0&0&0&...&0.5&2&0.5\\\\0.5&0&0&...&0&0.5&2\end{bmatrix}\begin{bmatrix}x_1\\\\x_2\\\\x_3\\\\...\\\\...\\\\...\\\\x_n\end{bmatrix}=\begin{bmatrix}p_1\\\\p_2\\\\p_3\\\\...\\\\...\\\\...\\\\p_{n}\end{bmatrix} 20.5.........00.50.52.........0000.5...0.5...00.........2.........00...0.5...0.5000.........20.50.50.........0.52x1x2x3.........xn=p1p2p3.........pn
不妨设原矩阵为A,设左上方n-1阶矩阵为B,设 c = [ 0.5 , 0 , 0 , 0... , 0.5 ] T c=[0.5,0,0,0...,0.5]^T c=[0.5,0,0,0...,0.5]T
则有如下关系:
A = [ B c c T 2 ] A=\begin{bmatrix}B&c\\c^T&2\end{bmatrix} A=[BcTc2]
代入方程可得
[ B [ x 1 x 2 . . . x n − 1 ] + c x n c T [ x 1 x 2 . . . x n − 1 ] + 2 x n ] = [ [ p 1 p 2 . . . p n − 1 ] p n ] \begin{bmatrix}B\begin{bmatrix}x_1\\x_2\\...\\x_{n-1}\end{bmatrix}+cx_{n}\\\\c^T\begin{bmatrix}x_1\\x_2\\...\\x_{n-1}\end{bmatrix}+2x_n\end{bmatrix}=\begin{bmatrix}\begin{bmatrix}p_1\\\\p_2\\\\...\\\\p_{n-1}\end{bmatrix}\\\\p_n\end{bmatrix} Bx1x2...xn1+cxncTx1x2...xn1+2xn=p1p2...pn1pn
取上方方块阵建立等式
不妨设 x i = u i x n + v i , i = 1 , 2 , . . . , n x_i=u_ix_n+v_i,i=1,2,...,n xi=uixn+vi,i=1,2,...,n代入等式
B ( u x n + v ) + c x n = P B(ux_n+v)+cx_n=P B(uxn+v)+cxn=P
B v = P Bv=P Bv=P
B u + c = 0 Bu+c=0 Bu+c=0
就把原方程求解转化为解两个n-1阶三对角矩阵
[ 2 0.5 0 . . . 0 0 0 0.5 2 0.5 . . . 0 0 0 . . . . . . . . . . . . . . . . . . . . . . . . . . . 0.5 2 0.5 . . . . . . . . . . . . . . . . . . . . . . . . . . . 0 0 0 . . . 0.5 2 0.5 0 0 0 . . . 0 0.5 2 ] [ u 1 u 2 u 3 . . . . . . . . . u n − 1 ] = [ − 0.5 0 . . . 0 . . . 0 − 0.5 ] \begin{bmatrix}2&0.5&0&...&0&0&0\\\\0.5&2&0.5&...&0&0&0\\\\...&...&...&...&...&...&...\\\\...&...&0.5&2&0.5&...&...\\\\...&...&...&...&...&...&...\\\\0&0&0&...&0.5&2&0.5\\\\0&0&0&...&0&0.5&2\end{bmatrix}\begin{bmatrix}u_1\\\\u_2\\\\u_3\\\\...\\\\...\\\\...\\\\u_{n-1}\end{bmatrix}=\begin{bmatrix}-0.5\\\\0\\\\...\\\\0\\\\...\\\\0\\\\-0.5\end{bmatrix} 20.5.........000.52.........0000.5...0.5...00.........2.........00...0.5...0.5000.........20.500.........0.52u1u2u3.........un1=0.50...0...00.5
[ 2 0.5 0 . . . 0 0 0 0.5 2 0.5 . . . 0 0 0 . . . . . . . . . . . . . . . . . . . . . . . . . . . 0.5 2 0.5 . . . . . . . . . . . . . . . . . . . . . . . . . . . 0 0 0 . . . 0.5 2 0.5 0 0 0 . . . 0 0.5 2 ] [ v 1 v 2 v 3 . . . . . . . . . v n − 1 ] = [ p 1 p 2 p 3 . . . . . . . . . p n − 1 ] \begin{bmatrix}2&0.5&0&...&0&0&0\\\\0.5&2&0.5&...&0&0&0\\\\...&...&...&...&...&...&...\\\\...&...&0.5&2&0.5&...&...\\\\...&...&...&...&...&...&...\\\\0&0&0&...&0.5&2&0.5\\\\0&0&0&...&0&0.5&2\end{bmatrix}\begin{bmatrix}v_1\\\\v_2\\\\v_3\\\\...\\\\...\\\\...\\\\v_{n-1}\end{bmatrix}=\begin{bmatrix}p_1\\\\p_2\\\\p_3\\\\...\\\\...\\\\...\\\\p_{n-1}\end{bmatrix} 20.5.........000.52.........0000.5...0.5...00.........2.........00...0.5...0.5000.........20.500.........0.52v1v2v3.........vn1=p1p2p3.........pn1
最后利用
x n = p n − 0.5 v 1 − 0.5 v n − 1 0.5 u 1 + 0.5 u n − 1 x_n=\frac{p_n-0.5v_1-0.5v_{n-1}}{0.5u_1+0.5u_{n-1}} xn=0.5u1+0.5un1pn0.5v10.5vn1解出 x n x_{n} xn然后迭代求解。
解三对角矩阵:
用Court分解法
在这里插入图片描述
上代码

void CF(double* p, int n,double* x){
	double z[10001];
	double u[10001]; 
	z[0]=p[0]/2;
	u[0]=0.25;
	double l;
	for(int i=1;i<n-1;i++){
		l=2-0.5*u[i-1];
		u[i]=0.5/l;
		z[i]=(p[i]-0.5*z[i-1])/l;
	}
	l=2-0.5*u[n-2];
	z[n-1]=(p[n-1]-0.5*z[n-2])/l;
	x[n-1]=z[n-1];
	for(int i=n-2;i>=0;i--){
		x[i]=z[i]-u[i]*x[i+1];
	}
}
void Price( int n, double p[] ){
	double p1[10001];
	p1[0]=p1[n-2]=-0.5;
	for(int i=1;i<n-2;i++) p1[i]=0;
	double u[10001],v[10001];
	CF(p1,n-1,u);
	CF(p,n-1,v);
	double x[10001];
	x[n-1]=(p[n-1]-0.5*v[0]-0.5*v[n-2])/(2+0.5*u[0]+0.5*u[n-2]);
	for(int i=0;i<n-1;i++){
		x[i]=u[i]*x[n-1]+v[i];
	}
	for(int i=0;i<n;i++){
		p[i]=x[i];
	}
}

参考:

https://wenku.baidu.com/view/262c84ac941ea76e59fa042c.html#
https://blog.csdn.net/qq_32096491/article/details/78213914


祝大家解题愉快!

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值