Xij * ai - L * bj >= 0
Xij * ai - U* bj <= 0
两边取对数来去除ai,bj前面的系数
有:
logbj - logai >= logXij - logU
logai - log bj <=logL - logXij
化成标准差分约束,建图,spfa,注意一个窍门,当入队总数大于2*(n+m)时就可以输出NO(因为一个点用来作为迭代点对其它点进行改进的平均次数为k,有办法证明对于通常的情况,k在2左右)
用vector实现,时间有点慢1078MS。。。
#include <list>
#include <map>
#include <set>
#include <queue>
#include <string>
#include <deque>
#include <stack>
#include <algorithm>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <limits.h>
#include <time.h>
#include <string.h>
using namespace std;
#define LL long long
#define PI acos(-1.0)
#define MAX INT_MAX
#define MIN INT_MIN
#define eps 1e-8
#define FRE freopen("a.txt","r",stdin)
#define MOD 1000000007
#define N 805
struct node{
int to;
double w;
};
int n,m;
double l,u;
vector<node> v[N];
double dis[N];
bool vis[N];
void build(int s,int t,double x){
node tmp;
tmp.to=t;
tmp.w=x;
v[s].push_back(tmp);
}
void init(){
int i,j,k;
for(i=0;i<N;i++)v[i].clear();
for(i=1;i<=n;i++){
for(j=1;j<=m;j++){
double x;
scanf("%lf",&x);
build(j+n,i,log(u/x));
build(i,j+n,log(x/l));
}
}
}
void spfa(){
queue<int> q;
while(!q.empty())q.pop();
int i,j,k;
memset(vis,0,sizeof(vis));
for(i=0;i<N;i++)dis[i]=MAX;
q.push(1);
dis[1]=0;
vis[1]=1;
int sum=0;
while(!q.empty()){
int top=q.front();
q.pop();
vis[top]=0;
for(i=0;i<v[top].size();i++){
int tmp=v[top][i].to;
double val=v[top][i].w;
if(dis[tmp]>dis[top]+val){
dis[tmp]=dis[top]+val;
if(!vis[tmp]){
vis[tmp]=1;
sum++;
if(sum>=2*(n+m)){
printf("NO\n");
return ;
}
q.push(tmp);
}
}
}
}
printf("YES\n");
return ;
}
int main(){
while(scanf("%d%d%lf%lf",&n,&m,&l,&u)!=EOF){
init();
spfa();
}
return 0;
}
本文探讨了一种解决复杂数学约束问题的方法,通过将原始问题转换为标准差分约束并使用SPFA算法求解。具体步骤包括对原始约束进行对数变换,构建图结构,采用SPFA算法进行搜索优化,以及引入一个关键技巧来判断最优解的存在性。通过实例分析,展示了算法的实现过程及应用效果。
258

被折叠的 条评论
为什么被折叠?



