Factory of XiaoE
Source : zhouguyue & lilu0355 & xiaoE | |||
Time limit : 1 sec | Memory limit : 64 M |
Submitted : 596, Accepted : 213
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
/* 由于所有原料都必须全部加工完,所以先处理出sum(v-w) 问题分析,如果要设计一个状态的话,显然状态与已经加工过的原料和你当前所在的原料有关,如果已经加工过的原料记为1,没加工过的原料记为0,那么已经加工过的原料的状态就可以压缩成一个数。所以,该题目的状态表示为: Dp[i][j]表示已经加工过的原料为i,当前所在的原料为j的最小转换代价。 相应的状态转移方程为dp[i][j]=min(dp[i^(1<<j)][k]+dis[k][j]); i^(1<<j)的意思是将j这个城市从i状态中去掉。 dis[k][j]是k和j之间转换的代价。 */ #include<iostream> #include<cstdio> #include<cstring> using namespace std; int map[20][20],dp[1<<15][20],n,m,v[20],sum; int main(){ //freopen("Cola.txt","r",stdin); while(scanf("%d%d",&n,&m)!=EOF){ sum=0; memset(dp,127/3,sizeof(dp)); int x,y; for(int i=1;i<=n;i++){ scanf("%d%d",&x,&y); sum+=y-x; } for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%d",&map[i][j]); dp[1<<(m-1)][m]=0; for(int i=0;i<(1<<n);i++){ if(i&(1<<(m-1))){ for(int j=1;j<=n;j++){ if((i&(1<<(j-1)))&&j!=m){ int tmp=i^(1<<(j-1)); for(int k=1;k<=n;k++){ if(tmp&(1<<(k-1))){ dp[i][j]=min(dp[i][j],dp[tmp][k]+map[k][j]); } } } } } } int ans=0x7fffffff; for(int i=1;i<=n;i++){ ans=min(ans,dp[(1<<n)-1][i]); } cout<<(sum-ans)<<endl; } }