Codeforces Round #325 (Div. 2) F:(meet in the middle)

本文详细介绍了如何通过哈希表优化算法效率,解决了一个看似需要暴力搜索的问题。首先,作者采用暴力搜索的方式遍历可能的状态,并利用哈希表存储已遍历过的状态以避免重复计算。接着,将搜索状态简化为二进制表示以减少存储需求。通过实例分析,展示了如何在复杂度较高的问题中引入高效的数据结构来提升算法性能。

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

一看题就觉得3^25暴力肯定挂。但是并不能想出思路

就当学习了,代码基本copy菊苣的。

前半部分暴力搜,将搜到的状态存在map里,这里只保存b-a和c-b是为了匹配方便

后半部分也是暴力搜状态,找到的状态去map里查询(比如后半搜到5,6,去map里找-5,-6)

感觉map好慢。看来有时候得去学习一下手写哈希表了

至于状态的保存,一开始想把每个操作保存为一个三位二进制,发现2^75位好像会爆啊。。

看了菊苣的才知道可以保存2位就好(3个状态)

膜拜菊苣。果然我还太渣

有个坑是全0 的数据。所以把ans初始化为-INF

#include"cstdio"
#include"queue"
#include"cmath"
#include"stack"
#include"iostream"
#include"algorithm"
#include"cstring"
#include"map"
#include"queue"
#include"vector"
#define ll long long

using namespace std;
const int MAXN = 200050;
const int MAXE = 400050;
const int INF = 0x3f3f3f3f;

map<pair<int,int>,pair<int,ll> >H;
pair<int ,ll> ans;
int n,s[30],l[30],m[30],w[30];


void dfs1(int a,int b,int c,int dep,ll s){//前半部分暴力
    if(dep>=(n+1)/2+1){
        pair<int,ll> t=H[pair<int,int>(a-b,b-c)];
        if(t.second==0) H[pair<int,int>(a-b,b-c)]=pair<int,ll>(a,s);
        else H[pair<int,int>(a-b,b-c)]=max(t,pair<int,ll>(a,s));//比较first
        return;
    }
    dfs1(a+l[dep],b+m[dep],c,dep+1,s<<2|1);
    dfs1(a+l[dep],b,c+w[dep],dep+1,s<<2|2);
    dfs1(a,b+m[dep],c+w[dep],dep+1,s<<2|3);
}

void dfs2(int a,int b,int c,int dep,ll s){
    if(dep>=n+1){
        pair<int,ll> t=H[pair<int,int>(b-a,c-b)];
        if(t.second==0) return ;
        ans=max(ans,pair<int,ll>(a+t.first,t.second<<(n-(n+1)/2<<1)|s));
        return;
    }
    dfs2(a+l[dep],b+m[dep],c,dep+1,s<<2|1);
    dfs2(a+l[dep],b,c+w[dep],dep+1,s<<2|2);
    dfs2(a,b+m[dep],c+w[dep],dep+1,s<<2|3);
}


int main(){
    ans.first=-INF;
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d%d%d",&l[i],&m[i],&w[i]);
    dfs1(0,0,0,1,0);
    dfs2(0,0,0,(n+1)/2+1,0);
    if(ans.first==-INF) printf("Impossible\n");
    else{
        for(int i=0;i<n;i++){
            s[i]=ans.second&3;
            ans.second>>=2;
        }
        for(int i=n-1;i>=0;i--){
            if(s[i]==1) printf("LM\n");
            else if(s[i]==2) printf("LW\n");
            else printf("MW\n");
        }
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/luxiaoming/p/5068095.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值