zoukankan      html  css  js  c++  java
  • UVALIVE 6958 Indoorienteering

    题目大意:有不超过14个点组成的完全图,给出邻接矩阵,问是否存在长度为W的欧拉回路?

         数据范围:n<=14, w<=1e15;

         standard input/output 7 s, 256 MB

    分析:直接暴力是14!的复杂度,显然不能通过;

       考虑折半搜索,我们取0号点为起点,然后把所有的点分成两半;

       两边分别暴力跑,最后检查一边,看另一边是否有可行的路径即可;

       复杂度为C(N,N/2)*(n/2)!;

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <algorithm>
    #include <climits>
    #include <cstring>
    #include <string>
    #include <set>
    #include <bitset>
    #include <map>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <cassert>
    #include <ctime>
    #define rep(i,m,n) for(i=m;i<=(int)n;i++)
    #define inf 0x3f3f3f3f
    #define mod 1000000007
    #define vi vector<int>
    #define pb push_back
    #define mp make_pair
    #define fi first
    #define se second
    #define ll long long
    #define pi acos(-1.0)
    #define pii pair<int,int>
    #define sys system("pause")
    #define ls (rt<<1)
    #define rs (rt<<1|1)
    #define all(x) x.begin(),x.end()
    const int maxn=1e5+10;
    const int N=4e5+10;
    using namespace std;
    ll gcd(ll p,ll q){return q==0?p:gcd(q,p%q);}
    ll qmul(ll p,ll q,ll mo){ll f=0;while(q){if(q&1)f=(f+p)%mo;p=(p+p)%mo;q>>=1;}return f;}
    ll qpow(ll p,ll q){ll f=1;while(q){if(q&1)f=f*p;p=p*p;q>>=1;}return f;}
    int n,m,k,t,c[2];
    ll w,d[14][14];
    set<ll>dp[14];
    bool flag;
    void dfs(int pos,int sta,ll now,int lim,int tp)
    {
        if(flag)return;
        int i;
        sta|=(1<<pos);
        if(lim==0)
        {
            if(tp==1)
            {
                rep(i,1,n-1)
                {
                    if(c[tp]>>i&1)continue;
                    if(dp[i].find(w-now-d[i][pos])!=dp[i].end())
                    {
                        flag=true;
                        return;
                    }
                }
            }
            else dp[pos].insert(now);
            return;
        }
        rep(i,0,n-1)
        {
            if((sta>>i&1)||(c[tp]>>i&1)==0)continue;
            dfs(i,sta,now+d[pos][i],lim-1,tp);
        }
    }
    int main(){
        int i,j;
        scanf("%d%lld",&n,&w);
        rep(i,0,n-1)rep(j,0,n-1)scanf("%lld",&d[i][j]);
        if(n==2)
        {
            if(d[0][1]+d[1][0]==w)puts("possible");
            else puts("impossible");
        }
        else
        {
            int all=((1<<n)-2);
            for(i=all-1;i;i=((i-1)&all))
            {
                if(__builtin_popcount(i)!=n/2)continue;
                c[0]=c[1]=0;
                rep(j,1,n-1)
                {
                    if(i>>j&1)c[0]|=(1<<j);
                    else c[1]|=(1<<j);
                }
                dfs(0,0,0,n/2,0);
                dfs(0,0,0,n-1-n/2,1);
                rep(j,0,n-1)dp[j].clear();
                if(flag)break;
            }
            puts(flag?"possible":"impossible");
        }
        return 0;
    }
  • 相关阅读:
    面向对象并不是必要的
    linq 总结
    垃圾自动回收的一个方案
    随手记 手机软件的不足,和开发自己理财软件的想法
    以人的角度去解决问题
    浮点数比较
    集中原则——软件设计之道
    云在何方
    我遇到了DLL地狱
    在C#.net中如何操作XML
  • 原文地址:https://www.cnblogs.com/dyzll/p/7612490.html
Copyright © 2011-2022 走看看