湖南省第八届程序设计竞赛K

Problem K. Cross-ShapedTests

 

There isan n*n matrix. Each number can be increased or decreased. If weincrease a number by x (which may be non-integer), the cost is c*x;If we decrease a number by x, the cost is d*x, where cand d are two non-negative integers.

 

Thetheoretical goal is to make every number equal to F, but in practice weonly do Q tests, each test is to specify a square, then adding all thenumbers in the same row or column, if the difference between the sum and (2n-1)Fis at most e, the test is successful.

 

Yourtask is to survive all the tests with minimal cost. It's not hard to see thatthe actual new matrix might be very different from the theoretical goal.

 

Input

The first line contains T (T<=100),the number of test cases. Each of the following lines begins with sixintegers n, c, d, F, e, Q(1<=n<=12, 0<=c,d<=100,-10<=F<=10, 0<=e<=5,1<=Q<=n2). Then an n*n matrix of integersfollowed. Each integer will have an absolute value of no greaterthan 10. Then Q lines followed. Each line contains two integers x,y (1<=x,y<=n), that means we make a test onthe square at row x, column y. Rows are numbered 1 to nfrom top to bottom, columns are numbered 1 to n from left toright. Each testcase is terminated by a blank line.

 

Output

For each test case, print the minimal cost,to five digits after the decimal point.

 

Sample Input                                 Output forSample Input

2

5 12 23 2 1 2

0 0 1 0 0

1 2 3 1 1

3 1 5 3 3

0 0 1 0 0

0 0 1 0 0

2 3

3 3

2 0 1 0 0 3

1 -1

-1 -2

1 1

2 1

2 2

58.00000

0.50000


 代码:

// Md. Mahbubul Hasan
#include<stdio.h>
#include<assert.h>
#include<cstring>
#include<algorithm>
using namespace std;

///
// Simon Lo's
// Simplex algorithm on augmented matrix a of dimension (m+1)x(n+1)
// returns 1 if feasible, 0 if not feasible, -1 if unbounded
// returns solution in b[] in original var order, max(f) in ret
// form: maximize sum_j(a_mj*x_j)-a_mn s.t. sum_j(a_ij*x_j)<=a_in
// in standard form.
// To convert into standard form:
// 1. if exists equality constraint, then replace by both >= and <=
// 2. if variable x doesn't have nonnegativity constraint, then replace by
// difference of 2 variables like x1-x2, where x1>=0, x2>=0
// 3. for a>=b constraints, convert to -a<=-b
// note: watch out for -0.0 in the solution, algorithm may cycle
// eps = 1e-7 may give wrong answer, 1e-10 is better

#define maxm 500
#define maxn 500
double inf = 1e100;
double eps = 1e-10;

void pivot(int m, int n, double a[maxm][maxn], int B[maxm], int N[maxn], int r, int c) {
	int i, j;
	swap(N[c], B[r]);
	a[r][c]=1/a[r][c];
	for (j=0; j<=n; j++)if (j!=c) a[r][j]*=a[r][c];
	for (i=0; i<=m; i++)if (i!=r) {
		for (j=0; j<=n; j++)if (j!=c)
			a[i][j]-=a[i][c]*a[r][j];
		a[i][c] = -a[i][c]*a[r][c];
	}
}
int feasible(int m, int n, double a[maxm][maxn], int B[maxm], int N[maxn]) {
	int r, c, i; double p, v;
	while (1) {
		for (p=inf, i=0; i<m; i++) if (a[i][n]<p) p=a[r=i][n];
		if (p>-eps) return 1;
		for (p=0, i=0; i<n; i++) if (a[r][i]<p) p=a[r][c=i];
		if (p>-eps) return 0;
		p = a[r][n]/a[r][c];
		for (i=r+1; i<m; i++) if (a[i][c]>eps) {
			v = a[i][n]/a[i][c];
			if (v<p) r=i, p=v;
		}
		pivot(m, n, a, B, N, r, c);
	}
}
int simplex(int m, int n, double a[maxm][maxn], double b[maxn], double& ret) {
	int B[maxm], N[maxn], r, c, i; double p, v;
	for (i=0; i<n; i++) N[i]=i;
	for (i=0; i<m; i++) B[i]=n+i;
	if (!feasible(m, n, a, B, N)) return 0;
	while (1) {
		for (p=0, i=0; i<n; i++) if (a[m][i]>p)
			p=a[m][c=i];
		if (p<eps) {
			for (i=0; i<n; i++) if (N[i]<n)
				b[N[i]]=0;
			for (i=0; i<m; i++) if (B[i]<n)
				b[B[i]]=a[i][n];
			ret = -a[m][n];
			return 1;
		}
		for (p=inf, i=0; i<m; i++) if (a[i][c]>eps) {
			v = a[i][n]/a[i][c];
			if (v<p) p=v, r=i;
		}
		if (p==inf) return -1;
		pivot(m, n, a, B, N, r, c);
	}
}
//

int n, c, d, F, e, Q, mat[20][20], qx[300], qy[300];

void IN(int a, int l, int h)
{
	assert(l<=a && a<=h);
}

void input()
{
	int i, j;

	scanf("%d%d%d%d%d%d",&n,&c,&d,&F,&e,&Q);
	IN(n,1,12);
	IN(c,0,100);
	IN(d,0,100);
	IN(F,-10,10);
	IN(e,0,5); 
	IN(Q,1,n*n);

	for(i=0;i<n;i++)
		for(j=0;j<n;j++)
		{
			scanf("%d",&mat[i][j]);
			IN(mat[i][j],-10,10);
		}

	for(i=0;i<Q;i++)
	{
		scanf("%d%d",&qx[i],&qy[i]);
		IN(qx[i],1,n);
		IN(qy[i],1,n);

		qx[i]--;
		qy[i]--;
	}
}

#define I_ID(r, c) (c)*(n) + (r)
#define D_ID(r, c) n*n + I_ID(r,c)

double A[maxm][maxn], B[maxn];

double process()
{
	memset(A,0,sizeof(A));

	int neq=2*Q, nvar=2*n*n;
	int cureq = 0;
	double ret;
	int i, j, status;

	for(i=0;i<Q;i++)
	{
		for(j=0;j<i;j++) if(qx[i]==qx[j] && qy[i]==qy[j]) break;
		if(i!=j) continue;

		A[cureq][nvar] = e + (2*n-1)*F;
		A[cureq+1][nvar] = e - (2*n-1)*F;

		for(j=0;j<n;j++) //row
		{
			A[cureq][nvar] -= mat[j][qy[i]];
			A[cureq+1][nvar] += mat[j][qy[i]];

			A[cureq][I_ID(j,qy[i])] = 1;
			A[cureq][D_ID(j,qy[i])] = -1;

			A[cureq+1][I_ID(j,qy[i])] = -1;
			A[cureq+1][D_ID(j,qy[i])] = 1;
		}

		for(j=0;j<n;j++) if(j!=qy[i])//col 
		{
			A[cureq][nvar] -= mat[qx[i]][j];
			A[cureq+1][nvar] += mat[qx[i]][j];

			A[cureq][I_ID(qx[i],j)] = 1;
			A[cureq][D_ID(qx[i],j)] = -1;

			A[cureq+1][I_ID(qx[i],j)] = -1;
			A[cureq+1][D_ID(qx[i],j)] = 1;
		}
		cureq+=2;
	}

	for(i=0;i<n;i++)
		for(j=0;j<n;j++)
		{
			A[cureq][I_ID(i,j)] = -c;
			A[cureq][D_ID(i,j)] = -d;
		}
	status = simplex(neq, nvar, A, B, ret);

	assert(status==1);

	return -ret;
}

int main()
{
	int T;
	double ans;

	scanf("%d",&T);
	IN(T,1,100);

	while(T--)
	{
		input();
		ans = process();
		printf("%.5lf\n",ans);
	}

	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值