zoj 3471 Most Powerful (状态压缩dp)

题意:两个原子如果碰撞会释放出相应的能量,并且其中有一个原子碰撞后会湮灭。

求所有碰撞状态中释放出的能量的最大值。


分析:由于最多只有10个原子,所以可以用二进制枚举所有状态,二进制位上为1表示

该原子已经湮灭。0表示还没有。

dp方程: dp[i]表示i状态下得到的最大能量。

dp[i|tmp]=max(dp[i|tmp],dp[i]+mp[k][j]);  

dp[i]+mp[k][j]表示 第j个原子和第k个原子碰撞,第j个原子湮灭产生的能量。

tmp是由i上转移过来的,tmp=i|(1<<j)。


#include<cstdio>
#include<iostream>
#include<cstring>
#define maxn (1<<10)
using namespace std;

int dp[maxn],mp[15][15];

int maxx(int x,int y)
{
    return x>y?x:y;
}

int main()
{
    int n,tot,tmp,ans;
    while(scanf("%d",&n)!=EOF)
    {
        if(n==0) break;
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                scanf("%d",&mp[i][j]);
            }
        }
        memset(dp,0,sizeof(dp));
        tot=(1<<10);
        for(int i=0;i<tot;i++)
        {
            for(int j=0;j<n;j++)
            {
                int tmp1=(1<<j);
                if((i&tmp1)==0)
                {
                    for(int k=0;k<n;k++)
                    {
                        int tmp2=(1<<k);
                        if((i&tmp2)==0 && j!=k)
                            dp[i|tmp1]=maxx(dp[i|tmp1],dp[i]+mp[k][j]);
                    }
                }
            }
        }
        ans=0;
        for(int i=0;i<tot;i++)
        {
            if(dp[i]>ans)
                ans=dp[i];
        }
        printf("%d\n",ans);
    }
    return 0;
}


也可以用个数组把所有状态存起来方便用。

即把10个位置每个原子湮灭的状态表示在数组state中。


#include<cstdio>
#include<iostream>
#include<cstring>
#define maxn (1<<10)+10
using namespace std;

int dp[maxn],mp[15][15];
int state[11]={1,2,4,8,16,32,64,128,256,512,1024};

int maxx(int x,int y)
{
    return x>y?x:y;
}

int main()
{
    int n,tot,ans;
    while(scanf("%d",&n)!=EOF)
    {
        if(n==0) break;
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                scanf("%d",&mp[i][j]);
            }
        }
        memset(dp,0,sizeof(dp));
        for(int i=0;i<state[n];i++)
        {
            for(int j=0;j<n;j++)   //枚举每一个原子
            {
                if((i&state[j])==0)   //如果这个原子还没被湮灭
                {
                    for(int k=0;k<n;k++)   //则找另一个还没湮灭的原子于j原子碰撞
                    {                         //使j原子湮灭
                        if((i&state[k])==0 && j!=k)
                            dp[i|state[j]]=maxx(dp[i|state[j]],dp[i]+mp[k][j]);
                    }
                }
            }
        }
        ans=0;
        for(int i=0;i<state[n];i++)
        {
            if(dp[i]>ans)
                ans=dp[i];
        }
        printf("%d\n",ans);
    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值