hdu3001 三进制 状态压缩dp

转自:

http://blog.csdn.net/u011721440/article/details/39738173



都过了这么久了。。。我连这么基础的状态压缩dp都不会。。

收获:

(1)没有关于树这种说法中。。要记得注意重边,,,

(2)原来的多进制是这样弄得。。

(3)他这里更新答案的时候是怎样更新的。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<string>
#include<cstring>
#include<iomanip>
#include<iostream>
#include<stack>
#include<cmath>
#include<map>
#include<vector>
#define ll long long
#define INF 1000000000
#define bug1 cout<<"bug1"<<endl;
#define bug2 cout<<"bug2"<<endl;
#define bug3 cout<<"bug3"<<endl;
using namespace std;
#define sf scanf
#define pf printf
#define mem(a,b) memset(a,b,sizeof(a));

const int inf=0x1f1f1f1f;
//2017年4月20日21:54:16

const int maxx=60000;
int e[12][12];
int n,m;
int tri[12];
int dig[maxx][12];
int dp[maxx][12];
void init(){
    tri[1]=1;
    for(int i=2;i<=11;++i){
        tri[i]=tri[i-1]*3;
    }
    for(int i=1;i<=tri[11];++i){
        int t=i;
        for(int j=1;j<=10;++j){
            dig[i][j]=t%3;
            t/=3;
            if(t==0)break;
        }
    }
}
int main(){
    init();
    while(~sf("%d%d",&n,&m)){
            int ans=inf;
        mem(e,inf);
        mem(dp,inf);

        for(int i=1;i<=m;++i){
            int u,v,c;
            sf("%d%d%d",&u,&v,&c);
            e[u][v]=e[v][u]=min(c,e[v][u]);
        }
        for(int i=1;i<=n;++i){
            dp[tri[i]][i]=0;
        }
        for(int s=1;s<tri[n+1];++s){
            int fg=1;
            for(int i=1;i<=n;++i){
                if(dig[s][i]==0) fg=0;
                if(dp[s][i]==inf)continue;
                for(int j=1;j<=n;++j){
                    if(j==i||dig[s][j]>=2||e[i][j]==inf)continue;
                    int v=s+tri[j];
                    dp[v][j]=min(dp[v][j],dp[s][i]+e[i][j]);
                }
            }
            if(fg){
                for(int i=1;i<=n;++i){
                    ans=min(ans,dp[s][i]);
                }
            }
        }
        if(ans==inf)ans=-1;
        pf("%d\n",ans);


    }
}

2017年5月6日09:25:11;

自己再做,还是有错。。  至少知道了多进制不能<<

#include<iostream>
#include<string>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<iomanip>
#include<queue>
#include<map>
#include<set>

using namespace std;
#define mem(a,b) memset(a,b,sizeof(a));
#define sf scanf
#define pf printf
const int INF=1e9;
const int N=15;
const int M=60000;
const int inf=0x3f3f3f3f;

int n,m;
//2017年5月6日08:42:30
int g[N][N];
int p[15];
int dig[M][11];
int d[M][11];
void init(){
    for(int i=0;i<=p[11];++i){
        int cnt=0;
        int t=i;
        for(int j=1;j<=10;++j){
            dig[i][j]=t%3;
            t/=3;
            if(t==0)break;
        }
    }
}

int main(){
    p[1]=1;//自己一开始把p[0]=1;,这是不对的。。
    for(int i=2;i<=11;++i){
        p[i]=p[i-1]*3;
    }
    init();
    while(~sf("%d%d",&n,&m)){
        mem(g,inf);mem(d,inf);
        for(int i=1;i<=n;++i)d[p[i]][i]=0;
        for(int i=1;i<=m;++i){
            int u,v,c;
            sf("%d%d%d",&u,&v,&c);
            g[u][v]=g[v][u]=min(g[v][u],c);
        }
        int ans=INF;
        for(int i=1;i<p[n+1];++i){
            int flag=1;
            for(int j=1;j<=n;++j){
                if(dig[i][j]==0){
                    flag=0;
                }
                if(d[i][j]==inf)continue;
                for(int v=1;v<=n;++v){
                    if(v!=j&&g[j][v]!=inf&&dig[i][v]<2){//注意三进制和二进制不同,,别用<<
                        //d[i+(1<<(v-1))][v]=min(d[i+(1<<(v-1))][v],d[i][j]+g[j][v]);
                        d[i+p[v]][v]=min(d[i+p[v]][v],d[i][j]+g[j][v]);
                    }
                }
            }
            if(flag){
                for(int j=1;j<=n;++j){
                    ans=min(ans,d[i][j]);
                }
            }
        }
        if(ans==INF)ans=-1;
        pf("%d\n",ans);
    }
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值