10.15模拟赛

美团的三道原题…好多人都ak了

「美团 CodeM 初赛 Round A」身体训练
随便推推 O(n2) 就过了…

「美团 CodeM 初赛 Round B」景区路线规划
事实证明爆搜没前途啊…考完发现只要加个记忆化就过了…
首先两个人肯定是独立的…搜索的过程中记忆化一下 dp[x][time][opt] 表示每个人到 x 点时间还剩time的贡献
事实证明我的记忆化水平不高啊…

double dfs(int x,int time,int opt)
{
    if(dp[x][time][opt]) return dp[x][time][opt];
    int i,down=0;
    for(i=head[x];i;i=e[i].next)
        if(time>=e[i].t+c[e[i].to]) ++down;
    double res=h[opt][x];
    for(i=head[x];i;i=e[i].next)
        if(time>=e[i].t+c[e[i].to])
            res+=dfs(e[i].to,time-e[i].t-c[e[i].to],opt)/down;
    return dp[x][time][opt]=res;
}

「美团 CodeM 初赛 Round B」送外卖2
最近在学状压,一眼就觉得是个状压题
3进制,0表示没拿到,1表示拿到了,2表示送到了
dp[x][state] 当前在 x 点状态为state
一重循环枚举状态
一重循环枚举当前在的位置
一重枚举订单
xjb转移一下//只用处理0,1的位可以不用进位好开心
然后算一下答案

#include<cstdio>
#include<algorithm>
#include<cstring>
#define INF 1e9
using namespace std;

struct task{int s,t,l,r;}T[11];
int n,m,q,ans,map[21][21],dp[21][59049+5],pow[11];

void init()
{
    scanf("%d %d %d",&n,&m,&q);
    int i,j,k,x,y,v;
    for(i=1,pow[0]=1;i<=q;++i) pow[i]=pow[i-1]*3;
    for(i=1;i<=n;++i)
        for(j=1;j<=n;++j)
            map[i][j]=INF;
    for(i=1;i<=n;++i) map[i][i]=0;
    for(i=1;i<=m;++i)
    {
        scanf("%d %d %d",&x,&y,&v);
        map[x][y]=min(map[x][y],v);
    }
    for(k=1;k<=n;++k)
        for(i=1;i<=n;++i)
            for(j=1;j<=n;++j)
                if(i!=j&&j!=k)
                    map[i][j]=min(map[i][j],map[i][k]+map[k][j]);
    for(i=1;i<=q;++i)
        scanf("%d %d %d %d",&T[i].s,&T[i].t,&T[i].l,&T[i].r);
}

int c[10];

int main()
{
    init();
    int i,j,state,now,id,tmp;
    for(i=0;i<pow[q];++i) for(j=1;j<=n;++j) dp[j][i]=INF;
    for(now=1;now<=n;++now)
        dp[now][0]=map[1][now];
    for(state=0;state<pow[q];++state)
        for(now=1;now<=n;++now)
            for(id=1;id<=q;++id)
            {
                tmp=state%pow[id]/pow[id-1];
                if(tmp==0)
                    if(dp[now][state]+map[now][T[id].s]>=T[id].l)
                        dp[T[id].s][state+pow[id-1]]=min(dp[T[id].s][state+pow[id-1]],dp[now][state]+map[now][T[id].s]);
                    else dp[T[id].s][state+pow[id-1]]=min(T[id].l,dp[T[id].s][state+pow[id-1]]);
                if(tmp==1)
                    if(dp[now][state]+map[now][T[id].t]<=T[id].r)
                        dp[T[id].t][state+pow[id-1]]=min(dp[T[id].t][state+pow[id-1]],dp[now][state]+map[now][T[id].t]);
            }
    ans=0;
    for(state=0;state<pow[q];++state)
    {
        for(i=1;i<=n;++i)
            if(dp[i][state]!=1e9)
            {
                tmp=0;
                for(j=1;j<=q;++j) if(state%pow[j]/pow[j-1]==2) ++tmp;
                ans=max(ans,tmp);
            }
    }
    printf("%d\n",ans);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值