先来篇论文线性规划与单纯形算法
按列存系数矩阵T了无数发后,才知道原来二维数组按行遍历会比按列遍历快辣么多。。
bzoj3112 / luogu P3337
tle代码(按列遍历)
#include<stdio.h>
#include<iostream>
#include<math.h>
using namespace std;
double A[10010][1010],B[1010],C[10010],e=1e-7,ans=0;
int n,m;
void piv(int u,int v){
int i,j;
B[v]/=A[u][v];
for(i=1;i<=n;i++) if(i!=u) A[i][v]/=A[u][v];
A[u][v]=1/A[u][v];
for(j=1;j<=m;j++){
if(j!=v&&fabs(A[u][j])>e){
for(i=1;i<=n;i++) if(i!=u) A[i][j]-=A[u][j]*A[i][v]; //按列遍历
B[j]-=A[u][j]*B[v];
A[u][j]*=-A[u][v];
}
}
ans+=C[u]*B[v];
for(i=1;i<=n;i++) if(i!=u) C[i]-=C[u]*A[i][v];
C[u]*=-A[u][v];
}
int main(){
int i,j,a,b,c;
scanf("%d%d",&m,&n);
for(i=1;i<=m;i++) scanf("%lf",&B[i]);
for(i=1;i<=n;i++){
scanf("%d%d%d",&a,&b,&c);
C[i]=c;
for(j=a;j<=b;j++) A[i][j]=1;
}
while(1){
double mi=1e18;
for(a=1;a<=n;a++) if(C[a]>e) break;
if(a>n) break;
for(i=1;i<=m;i++){
if(A[a][i]>e&&mi>B[i]/A[a][i]){
mi=B[i]/A[a][i];
b=i;
}
}
if(mi==1e18) break;
piv(a,b);
}
long long x=ans+0.5;
cout<<x<<endl;
return 0;
}
ac代码(按行遍历)
#include<stdio.h>
#include<math.h>
#include<iostream>
using namespace std;
double A[1010][10010],B[1010],C[10010],ans=0,e=1e-7;
int n,m;
void piv(int u,int v){
int i,j;
B[u]/=A[u][v];
for(i=1;i<=n;i++) if(v!=i) A[u][i]/=A[u][v];
A[u][v]=1/A[u][v];
for(i=1;i<=m;i++){
if(i!=u&&fabs(A[i][v])>e){
for(j=1;j<=n;j++) if(j!=v) A[i][j]-=A[i][v]*A[u][j]; //按行遍历
B[i]-=A[i][v]*B[u];
A[i][v]*=-A[u][v];
}
}
ans+=B[u]*C[v];
for(i=1;i<=n;i++) if(i!=v) C[i]-=C[v]*A[u][i];
C[v]*=-A[u][v];
}
int main(){
int i,j,a,b,c;
scanf("%d%d",&m,&n);
for(i=1;i<=m;i++) scanf("%lf",&B[i]);
for(i=1;i<=n;i++){
scanf("%d%d%lf",&a,&b,&C[i]);
for(j=a;j<=b;j++) A[j][i]=1;
}
while(1){
for(a=1;a<=n;a++) if(C[a]>e) break;
if(a>n) break;
double mi=1e18;
for(i=1;i<=m;i++){
if(A[i][a]>e&&mi>B[i]/A[i][a]){
b=i;
mi=B[i]/A[i][a];
}
}
if(mi==1e18) break;
piv(b,a);
}
long long x=ans+0.5;
cout<<x<<endl;
return 0;
}
bzoj 1061
线性规划鸭。。。
#include<iostream>
#include<math.h>
#include<stdio.h>
using namespace std;
int n,m;
double A[10010][1010],B[10010],C[1010],e=1e-6,ans=0;
void piv(int u,int v){
int i,j;
for(i=1;i<=n;i++) if(i!=v) A[u][i]/=A[u][v];
B[u]/=A[u][v];
A[u][v]=1/A[u][v];
for(i=1;i<=m;i++){
if(i!=u&&fabs(A[i][v])>e){ //注意精度
for(j=1;j<=n;j++) if(j!=v) A[i][j]-=A[i][v]*A[u][j];
B[i]-=B[u]*A[i][v];
A[i][v]*=-A[u][v];
}
}
ans+=B[u]*C[v];
for(i=1;i<=n;i++) if(i!=v) C[i]-=C[v]*A[u][i];
C[v]*=-A[u][v];
}
int main(){
int i,j,a,b,c;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++) scanf("%lf",&C[i]); //C[i]为第i个不等式等号右边的常数
for(i=1;i<=m;i++){
scanf("%d%d%lf",&a,&b,&B[i]); //B[i]为目标函数第i个未知数的的系数
for(j=a;j<=b;j++) A[i][j]=1; //A[i][j]为第j个不等式第i个未知数的系数
}
while(1){
for(b=1;b<=n;b++) if(C[b]>e) break;
if(b>n) break;
double mi=1e18;
for(i=1;i<=m;i++){
if(A[i][b]>e&&mi>B[i]/A[i][b]){
a=i;
mi=B[i]/A[i][b];
}
}
piv(a,b);
}
long long x=ans+0.5;
printf("%lld\n",x);
return 0;
}
bzoj 3265
同上。。