状压DP(挑战程序设计竞赛)

POJ - 2686

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=10;
const int maxm=35;
const int INF=1<<29;
int n,m,a,b,p;
double ans;
double t[maxn];
double mz[maxm][maxm];
double dp[1<<maxn][maxm];
void DP()
{
    for(int s=(1<<n)-1;s>=0;s--)
    {
        for(int v=1;v<=m;v++)
          for(int i=0;i<n;i++)
        {
            if((s>>i)&1)
            {
                for(int u=1;u<=m;u++)
                    if(mz[v][u]>=0)
                    dp[s&~(1<<i)][u]=min(dp[s&~(1<<i)][u],dp[s][v]+mz[v][u]/t[i]);
            }
        }
    }

}
int main()
{
    while(cin>>n>>m>>p>>a>>b)
    {
        if(n==0&&m==0&&p==0&&a==0&&b==0) break;
        memset(mz,-1,sizeof(mz));
        for(int i=0;i<(1<<n);i++)
            fill(dp[i],dp[i]+m+1,INF);
        ans=INF;
        for(int i=0;i<n;i++)
          cin>>t[i];
        for(int i=0;i<p;i++)
        {
          int x,y;
          cin>>x>>y;
          cin>>mz[x][y];
          mz[y][x]=mz[x][y];
         }
         dp[(1<<n)-1][a]=0;
         DP();
         for(int i=0;i<(1<<n);i++)
            ans=min(ans,dp[i][b]);
         if(ans==INF)
            cout<<"Impossible"<<endl;
         else cout<<ans<<endl;
    }
    return 0;
}

POJ - 2441

#include<iostream>
#include<string.h>
using namespace std;
typedef long long ll;
const int maxn=21;
const int maxm=21;
const int INF=1<<29;
int n,m,ans;
int mz[maxm][maxm];
int dp[1<<maxm];
void DP()
{
    for(int i=0;i<n;i++)
    {
        for(int s=(1<<m)-1;s>=0;s--)
        {
            if(!dp[s]) continue;
            for(int j=0;j<m;j++)
            {
                if(s&(1<<j)) continue;
                if(mz[i+1][j]==0)continue;
                dp[s|(1<<j)]+=dp[s];
            }
            dp[s]=0;
        }
    }
}
int main()
{
    while(cin>>n>>m)
    {
        memset(mz,0,sizeof(mz));
        memset(dp,0,sizeof(dp));
        for(int i=0;i<n;i++)
        {
            int k,temp;
            cin>>k;
            for(int j=0;j<k;j++)
            {
              cin>>temp;
              temp--;
              mz[i+1][temp]=1;
            }
        }
         dp[0]=1;
         DP();
         ans=0;
         for(int i=0;i<(1<<m);i++)
            ans+=dp[i];
         cout<<ans<<endl;
    }
    return 0;
}

POJ - 3254

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=15;
const int maxm=15;
const int mod=1e8;
const int INF=1<<29;
int n,m,ans;
int mz[maxm][maxm];
int v[1<<maxn];
int dp[maxm][1<<maxm];
void init()//筛选出不相邻的状态
{
    int cnt=0;
    for(int i=0;i<(1<<maxn);i++)
    {
        if(!(i&(i<<1)))
         v[cnt++]=i;
    }
}
int C(int x,int y)
{
    for(int i=0;i<n;i++)
        if((y&(1<<i))&&!mz[x][i])
        return 1;
    return 0;
}
void DP()
{
    for(int i=0;i<m;i++)
    {
        for(int s=0;v[s]<(1<<n);s++)
        {
            if(C(i,v[s])) continue;
            if(i==0) {dp[i][s]=1; continue;}
            for(int j=0;v[j]<(1<<n);j++)
            {
                if((v[j]&v[s])==0)
                dp[i][s]+=dp[i-1][j];
            }
        }
    }
}
int main()
{
    init();
    while(cin>>m>>n)
    {
        memset(mz,0,sizeof(mz));
        memset(dp,0,sizeof(dp));
        for(int i=0;i<m;i++)
            for(int j=0;j<n;j++)
                cin>>mz[i][j];
         DP();
         ans=0;
         for(int i=0;v[i]<(1<<n);i++)
            ans=(ans+dp[m-1][i])%mod;
         cout<<ans<<endl;
    }
    return 0;
}

POJ - 2836

#include<iostream>
#include<string.h>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
const int maxn=16;
int n,m,ans,cnt;
int dp[1<<maxn];
int x[maxn],y[maxn],S[maxn*maxn];
int cover[maxn*maxn];
void init()
{
    cnt=0;
    for(int i=1;i<n;i++)
     for(int j=0;j<i;j++)
    {
        int w=abs(x[i]-x[j]);
        int h=abs(y[i]-y[j]);
        if(w==0) w=1;  //可能会存在x/y相同的情况,记得处理,不然面积就变成0了orz
        if(h==0) h=1;
        S[cnt]=w*h;
        cover[cnt]=0;
        for(int k=0;k<n;k++)
        {
            if(x[k]>=min(x[i],x[j])&&x[k]<=max(x[i],x[j])&&
               y[k]>=min(y[i],y[j])&&y[k]<=max(y[i],y[j]))
                cover[cnt]|=(1<<k);
        }
        cnt++;
    }
}
void DP()
{
   dp[0]=0;
    for(int s=0;s<(1<<n);s++)
    {
        if(dp[s]!=0x3f)
        for(int j=0;j<cnt;j++)
        {
            int temp=s|cover[j];
            if(temp!=s)
             dp[temp]=min(dp[temp],dp[s]+S[j]);
        }
    }
}
int main()
{
    while(cin>>n&&n)
    {
        memset(dp,0x3f,sizeof(dp));
        for(int i=0;i<n;i++)
            cin>>x[i]>>y[i];
        init();
        DP();
        cout<<dp[(1<<n)-1]<<endl;
    }
    return 0;
}

 

posted @ 2018-02-01 22:25  #Egoist#  阅读(509)  评论(0编辑  收藏  举报