ZF_20160921_Topcoder

本文介绍了一道Topcoder SRM522 Div1 03的解题思路及实现代码。该问题涉及点的顺序判断,并通过动态规划求解最优解。文章详细展示了如何遍历所有可能的点组合,判断点是否可以按特定顺序排列,最终确定可消除的点数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

SRM522 div1 03

#include<cstdio>
#include<cstring>
#include<vector>
#include<set>
#include<map>
#define ll long long
#define For(ir,S) for(typeof(S.begin()) ir = S.begin(); ir!=S.end(); ir++)
using namespace std;
const int _=60;
class PointErasing
{
public:
    int ok(int a,int b,int c)
    {
        return a<b and b<c or a>b and b>c;
    }
    int ok(int x1,int y1,int x2,int y2,int x3,int y3)
    {
        return ok(x1,x2,x3) and ok(y1,y2,y3);
    }
    int n;
    int can[_],must[_],ins[_][_][_];
    int vis[_];
    set<ll>S;
    map<ll,int>M;
    vector<int> getOutcomes(vector<int> y)
    {
        memset(ins,0,sizeof ins);
        memset(can,0,sizeof can);
        memset(must,0,sizeof must);
        n=y.size();
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                for(int k=0;k<n;k++)
                {
                    ins[i][j][k]=ok(j,y[j],i,y[i],k,y[k]);
                    if(ins[i][j][k])
                        can[i] = 1;
                }
            }
        }
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                for(int k=0;k<n;k++)
                    if(!can[j] and !can[k] and ins[i][j][k])
                        must[i]=1;
        S.clear();
        /// j,k包含哪些点
        for(int j=0;j<n;j++)
        {
            for(int k=0;k<n;k++)
            {
                ll t=0;
                for(int i=0;i<n;i++)
                {
                    if(!must[i] and ins[i][j][k])
                        t|=1LL<<i;
                    S.insert(t);
                }
            }
        }
        M.clear();
        M[1]=0;
        For(it,S)
        {
            For(ir,M)
            {
                ll t = *it;
                if(ir->first==0 or (t & ir->first) != ir->first)
                {
                    M.insert(make_pair(t,ir->second+__builtin_popcountll(t & (~ir->first))));
                }
            }
        }
        memset(vis,0,sizeof vis);
        For(it,M)
            vis[it->second]=1;
        vector<int>res;
        int cnt=0;
        for(int i=0;i<n;i++)
            cnt+=must[i];
        n-=cnt;
        for(int i=50;i>=0;i++)
        {
            if(vis[i])
                res.push_back(n-i));
        }
        return res;
    }
};

int main()
{

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值