题目链接:点击打开链接
题意描述:给出一些不等式,求最多可以满足多少不等式同时成立?
解题思路:最大团问题
分析:
1、我们可以根据不等式之间的关系建图,如果两个不等式同时成立,则在这两个顶点之间建立一条边,问题转化为求这张图的最大团问题;
2、由于规模n<=50比较小,所以我们可以使用dfs搜索找出最大团
注意:
1、x不一定是整数
2、读字符时建议用字符串读入,去st[0]即可,这样可以解决很多换行问题尤其/n/r
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#define MAXN 60
#define eps 1e-8
#define minx 1e-5
using namespace std;
struct point{
int op;
double v;///题目并未说明x是整数
}p[MAXN];
struct MAX_CLIQUE {///N<=100,否则超时,节点下标从一开始
static const int N=60;
bool G[N][N];
int n, Max[N], Alt[N][N], ans;
bool DFS(int cur, int tot) {
if(cur==0) {
if(tot>ans) {
ans=tot;
return 1;
}
return 0;
}
for(int i=0; i<cur; i++) {
if(cur-i+tot<=ans) return 0;
int u=Alt[tot][i];
if(Max[u]+tot<=ans) return 0;
int nxt=0;
for(int j=i+1; j<cur; j++)
if(G[u][Alt[tot][j]]) Alt[tot+1][nxt++]=Alt[tot][j];
if(DFS(nxt, tot+1)) return 1;
}
return 0;
}
int MaxClique() {
ans=0, memset(Max, 0, sizeof(Max));
for(int i=n-1; i>=0; i--){
int cur=0;
for(int j=i+1; j<n; j++) if(G[i][j]) Alt[1][cur++]=j;
DFS(cur, 1);
Max[i]=ans;
}
return ans;
}
}mc;
bool isok(point a,point b){
if(a.op==b.op){
if(a.op==0&&((a.v-b.v>eps)||(b.v-a.v>eps))) return false;
return true;
}
if(a.op>b.op) swap(a,b);
if(a.op==-1&&b.op==0){
if(b.v-a.v>=-eps) return false;
return true;
}
if(a.op==-1&&b.op==1){
if(b.v>=a.v-minx-eps) return false;
return true;
}
if(a.op==0&&b.op==1){
if(a.v-b.v<=eps) return false;
return true;
}
}
int main(){
while(scanf("%d",&mc.n)!=EOF){
char tmp[5],st[5];
double v;
for(int i=0;i<mc.n;++i){
scanf("%s%s%lf",tmp,st,&v);///getchar()过滤存在问题,最安全的还是字符串
if(!strcmp(st,"=")){p[i].op=0;p[i].v=v;}
else if(!strcmp(st,">")){p[i].op=1;p[i].v=v;}
else if(!strcmp(st,"<")){p[i].op=-1;p[i].v=v;}
else if(!strcmp(st,">=")){p[i].op=1;p[i].v=v-minx;}
else if(!strcmp(st,"<=")){p[i].op=-1;p[i].v=v+minx;}
}
memset(mc.G,false,sizeof(mc.G));
for(int i=0;i<mc.n;++i) for(int j=i+1;j<mc.n;++j)
if(isok(p[i],p[j]))
mc.G[i][j]=mc.G[j][i]=true;
printf("%d\n",mc.MaxClique());
}
return 0;
}