状态压缩 dp 杭电1074

//状态压缩 DP
//我勒个去 入门题卡了我两天  
// dp[i]用i的二进制表示一种状态 例如:i=3  0011表示第0个和第1个物品在集合中 第2个和第3个物品不在集合中


#include<stdio.h>
#include<string.h>
#include<stack>


using namespace std;


#define N 16
struct node
{
char name[110];
int dl;
int cost;
}km[N];




#define inf 0x7fffffff


int line[1<<N];
int dp[1<<N];
int n,limit;


void init()
{
scanf("%d",&n);
int i;
for(i=0;i<n;i++)
{
scanf("%s %d %d",km[i].name,&km[i].dl,&km[i].cost);


}
limit=1<<n;
for(i=0;i<limit;i++)
dp[i]=inf;
dp[0]=0;
memset(line,-1,sizeof(line));


}


int add(int m,int k)
{
int top,cur,i;
top=cur=0;


for(i=0;i<n;i++)
{
if(m&(1<<i))
top+=km[i].cost;
}
cur=top-km[k].cost;
m=m-(1<<k);
int s=0;
for(i=0;i<n;i++)
{
if(!(m&(1<<i)))
{
if(km[i].dl<top)
{
s+=(top-cur)<(top-km[i].dl)?(top-cur):(top-km[i].dl);
}
}
}
return s;
}
void zt_dp()
{
int i,j,k,ad;
for(i=0;i<limit;i++)
{
for(j=0;j<n;j++)//求出dp[i]的最小值 即以i集合中的每个元素为最后加入集合的元素就出扣分最少的
{
if(i&(1<<j))//判断第j个元素是否在i集合中
{
ad=add(i,j);
if(dp[i-(1<<j)]+ad<dp[i])
{
dp[i]=dp[i-(1<<j)]+ad;
line[i]=j;
}
if(dp[i-(1<<j)]+ad==dp[i])//保证输出时是字典顺序
{
line[i]=j;
}


}
}
}
}


void print()
{
int index;
printf("%d\n",dp[limit-1]);
stack<int>q;
index=limit-1;
while(index!=0)
{
q.push(line[index]);
index=index-(1<<line[index]);

}
while(!q.empty())
{
printf("%s\n",km[q.top()].name);
q.pop();
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
init();
zt_dp();
print();
}
return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值