CF 79D. Password

题目链接:D. Password


我是在这篇博客 看到的,这道题目一开始拿到一点想法都没有,感觉就根本不可以搞……

看了解题报告才明白,Orz


具体看上面的解题报告吧! 感觉上面解题报告的代码写的不好,容易让人看不明白


经过瘦身的代码如下:

#include<cstdio>
#include<cstring>
#include<set>
#include<map>
#include<iostream>
#include<queue>
#include<algorithm>

using namespace std;

const int maxn=10010;
const int inf=0x3fffffff;
int d[maxn],x[20],a[100],dp[1<<20],w[20][20];
bool vis[maxn];

int main()
{
    int n,k,l;
    while(scanf("%d%d%d",&n,&k,&l)==3)
    {
        memset(vis,0,sizeof(vis));
        for(int i=0;i<k;i++) scanf("%d",&x[i]),vis[x[i]]=1;
        for(int i=0;i<l;i++) scanf("%d",&a[i]);
        sort(a,a+l);
        l=unique(a,a+l)-a;
        k=0;
        for(int i=0;i<=n;i++)
          if(vis[i]!=vis[i+1]) x[k++]=i;
        /*for(int i=0;i<k;i++)
          cout<<x[i]<<" ";
        cout<<endl;*/
        for(int i=0;i<k;i++)
        {
            priority_queue<pair<int,int> > q;
            fill(d,d+n+1,inf);
            d[x[i]]=0;
            for(q.push(make_pair(0,x[i]));!q.empty();)
            {
                int u=q.top().second;
                int dis=-q.top().first;
                q.pop();
                if(d[u]!=dis) continue;
                for(int j=0;j<l;j++)
                {
                    if(u-a[j]>=0&&d[u-a[j]]>dis+1)
                        d[u-a[j]]=dis+1,q.push(make_pair(-dis-1,u-a[j]));
                    if(u+a[j]<=n&&d[u+a[j]]>dis+1)
                        d[u+a[j]]=dis+1,q.push(make_pair(-dis-1,u+a[j]));
                }
            }
            for(int j=0;j<k;j++) w[i][j]=d[x[j]];
        }
        fill(dp,dp+(1<<k),inf);
        dp[0]=0;
        for (int mask = 0 ; mask < (1<<k); mask++)
        {
            int u;
            for(u=0;u<k;u++) if((mask&(1<<u))==0) break;
            if (u >= k ) continue;
            for(int v = u+1; v < k; v++ )
               if ( (mask&(1<<v)) == 0)
               {
                    int _mask = mask ^ (1<<u) ^ (1<<v);
                    dp[_mask] = min(dp[_mask], dp[mask] + w[u][v]);
               }
        }
        printf("%d\n", dp[(1<<k)-1] == inf ? -1 : dp[(1<<k)-1]);
    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值