(简单) 状态压缩dp HOJ 2665 Factory of XiaoE

来源:互联网 发布:碧柔防晒知乎 编辑:程序博客网 时间:2024/06/05 10:57

Factory of XiaoE

Source : zhouguyue & lilu0355 & xiaoETime limit : 1 secMemory limit : 64 M

Submitted : 515, Accepted : 171

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 12 42 32 50 1 21 0 12 1 0

Sample Output

4


题意:要求生产n个产品,每件产品有对应的购入价格和卖出价格,但一次只能生产一件,转到生产另一件时需要花费一定的成本,问要生产全部的产品并且收益最大是多少?

思路:题目规模很小,所以可能是状态压缩的题目,我们用一个二进制数代表目前每个产品是否被生产,已经生产用1表示,还没生产用0表示,那么状态转移方程式dp[to][k] = min(dp[from][j]+w[j][k],dp[to][k]) w[j][k]表示从j转到k需要的成本,初始化条件是全部设为无穷大,然后dp[1<<(m-1)][m-1]=0 因为一开始是生产第m件产品,不需要转生产的成本。

代码:

#include<iostream>
#include<string>
#include<algorithm>
using namespace std;

const int maxn = 1<<16;
int dp[maxn][17];
const int inf = 0xfffffff;


int n,m;
int w[20][20];

int main()
{
while (scanf("%d%d",&n,&m)==2)
{
int ans = 0 , tem;
for (int i = 1 ; i <= n ; ++i)
{
scanf("%d",&tem);
ans -= tem;
scanf("%d",&tem);
ans += tem;
}
for (int i = 0 ; i < n ; ++i)
for (int j = 0; j < n ; ++j)
scanf("%d",&w[i][j]);

int max_state = 1 << n;
for (int s = 0 ; s < max_state ; ++s)
for (int j = 0 ; j < n ; ++j)
dp[s][j] = inf;
dp[1<<(m-1)][m-1] = 0;
for (int s = 1<<(m-1) ; s < max_state ; ++s)
{
for (int j = 0 ; j < n ; ++j) if (s&(1<<j))
{
for (int k = 0 ; k < n ; ++k) if (s^(1<<k))
{
int to = s+(1<<k);
dp[to][k] = min(dp[to][k],dp[s][j]+w[j][k]);
}
}
}
int ret = 0;
for (int i = 1 ; i < n ; ++i)
if (dp[max_state-1][ret] > dp[max_state-1][i])
ret = i;
printf("%d\n",ans-dp[max_state-1][ret]);
}
}


0 0