hoj2655Factory of XiaoE(状态压缩)

                                                   

Factory of XiaoE


Background

    XiaoE创办了一个小型加工厂,可以来加工n种工件。不过加工这些工件都是原材料的。于是他找到了供应原料的大老板超级大教主(SuperDaLord -> SDL - -!)。

    超级大教主告诉XiaoE说,“以咱们的关系,我绝对以最低价进给你原料,然后你把做好的工件拿来,我绝对以最高价收购。不过这事不能声张,不然Bin3、Lilu等人都来找我的话我就吃不消了。咱们控制一下数量吧,我每天早上把每种工件的原料进给你一份,晚上再从你那里收购每种工件各一件。”

    由于原料供应领域被超级大教主垄断,XiaoE别无选择(也就是买n种原料各一份,生产加工,卖出n种工件各一个)。而且XiaoE的工厂只有一台机器,加工完一种工件后需要对机器进行改造才能加工另一种工件,这个过程中有一定的成本。现在XiaoE想让自己一天内的收入尽可能的多。收入 = 工件卖出价 - 原料进购价 - 机器改造成本。我们假设XiaoE的工厂在一天内可以完成所有计划的生产和交易。

Input

    本题有多组测试数据,每组数据的第1行为两个整数n (n <= 15)和m(1 <= m <= n),以空格分隔,分别表示工厂可以来加工工件的数目与初始状态下机器可以加工的工件。以下n行每行有2个正整数,分别表示对应工件的进购价和卖出价 (均不超过105)。接下来给出一个n*n的矩阵(对称阵),表示机器在生产n个工件的工作状态间转换的改造成本。(100以内的非负整数)

Output

    对于每组输入,输出一个整数,表示XiaoE在一天内的最大收入。

Sample Input

3 1
2 4
2 3
2 5
0 1 2
1 0 1
2 1 0

Sample Output

4

刚开始m的意义没用看清楚,想了一个小时,结果却只是裸的状态压缩dp,
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <cmath>
#include <ctime>
#include <vector>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
#define INF 0x3f3f3f3f
#define inf -0x3f3f3f3f
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define mem0(a) memset(a,0,sizeof(a))
#define mem1(a) memset(a,-1,sizeof(a))
#define mem(a, b) memset(a, b, sizeof(a))
typedef long long ll;
const int maxn=16;
int dp[1<<maxn][maxn];
int mp[16][16];

int main(){
   int n,m;
   while(scanf("%d%d",&n,&m)!=EOF){
        for(int i=0;i<(1<<n);i++){
            fill(dp[i],dp[i]+n+1,INF);
        }
        int u,v;
        int ans=0;
        for(int i=1;i<=n;i++){
            scanf("%d%d",&u,&v);
            ans+=(v-u);
        }
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                scanf("%d",&mp[i][j]);
        dp[0][m-1]=0;
        for(int s=1;s<(1<<n);s++){
            for(int i=0;i<n;i++){
                //if(((s>>i)&1)==0)     //注意这句话千万不能加
                    //continue;           //i==j这句话也不能加,不然的话例如dp[1][0]=0等无法实现
                for(int j=0;j<n;j++){
                    //if(i==j)
                        //continue;
                    if(((s>>j)&1)==0||dp[s^(1<<j)][i]==INF)
                        continue;
                    dp[s][j]=min(dp[s][j],dp[s^(1<<j)][i]+mp[i][j]);
                    //printf("s is %d i is %d j is %d ",s,i,j);
                    //printf("dp[%d][%d] is %d\n",s,i,dp[s][j]);
                }
            }
        }
        int ans1=INF;
        for(int i=0;i<n;i++)
            ans1=min(ans1,dp[(1<<n)-1][i]);
        printf("%d\n",ans-ans1);
   }
   return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值