hihocoder 1223 : 不等式(最大团问题)

题目链接:点击打开链接

题意描述:给出一些不等式,求最多可以满足多少不等式同时成立?


解题思路:最大团问题

分析:

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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值