hdu 1074 状态压缩dp

//hdu 1074 状态压缩dp
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<istream>
#include<vector>
#include<math.h>
#include<stack>
#include<algorithm>
#define mod 10000009
#define maxn 9999999999
#define long long ll
using namespace std;
struct Job
{
	char name[205];
	int time, dead;
};
struct Choose
{
	int min, last,pre,now;
};

int main()
{
	//freopen("d:\\in.txt", "r", stdin);
	//freopen("d:\\inn.txt", "w", stdout);
	int T;
	scanf("%d", &T);
	while (T--)
	{
		Choose ch[1 << 15 + 1];
		Job job[16];
		int t, i,all,j;
		scanf("%d", &t);
		all = (1 << t) - 1;
		//printf("all=%d\n",all);
		for (i = 1;i <= all;i++)
		{
			ch[i].pre = -1;
			ch[i].min = 99999999999;
			ch[i].last = 0;
			ch[i].now = 0;
		}
		for (i = 1;i <= t;i++)
		{
			scanf("%s%d%d", job[i].name,&job[i].dead, &job[i].time);
			int y=1<<(i-1),x=job[i].time-job[i].dead;
			if(x<0)
                x=0;
			ch[y].min=x;
			ch[y].last=job[i].time;
            ch[y].now=i;
		}
		for (i = 1;i <= all;i++)
			for (j = 0;j < t;j++)
			{
			    int yy=1<<j;
			    //printf("i=%d yy=%d %d \n",i,yy,i&yy);
				if ((i&yy)==0)
				{
					int ii, jj;
					ii = ch[i].last + job[j + 1].time - job[j + 1].dead;
					//printf("ch[%d].last=%d  ii=%d \n",i,ch[i].last,ii);
					if (ii < 0)
						ii = 0;
					jj = (1 << j) + i;
					//printf("ch[%d].min=%d     ii=%d + ch[i].min=%d = %d\n",jj,ch[jj].min,ii,ch[i].min,ii+ch[i].min);
					if (ch[jj].min>ii+ch[i].min)
					{
						ch[jj].min = ii+ch[i].min;
						ch[jj].last = job[j+1].time+ch[i].last;
						//printf("ch[%d].last=%d   job[%d].time=%d+ch[%d].last=%d\n",jj,ch[jj].last,j,job[j].time,i,ch[i].last);
						ch[jj].pre = i;
						ch[jj].now = j + 1;
					}
                }
            }                            //注意搜索是是从小到大,不必要再考虑字典序的问题
		printf("%d\n", ch[all].min);
		stack<int> q;
		i = all;
		while (i!= -1)
		{
			q.push(ch[i].now);
			i = ch[i].pre;
		}
		while (!q.empty())
		{
			int front = q.top();
			q.pop();
			printf("%s\n", job[front].name);
		}
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值