HDU1074:Doing Homework (状压DP)

link

Question meaning: Give you a number of assignments, assignment deadlines, and the time required to complete the assignments, but if an assignment exceeds its deadline, then one point will be deducted. Ask how to arrange the order of writing assignments to minimize the deductions, if there are more This kind of solution is to output the solution with the smallest lexicographic order. When these jobs are given, the lexicographical order is ascending.

Idea: Because there are only 15 jobs at most, so press dp, let dp [i] [j] be the last completed job is i, the status of the completed job is j, enumerate the next job to be completed, calculate the completion of these The total time required for the job is recorded as k, then the transfer is dp[ next] [j | (1<<next)] = min(dp[ i ][ j] + finsh(j) + a[next].f-a [next].d) (next is a job not in j). The answer is min( dp[ 1—n] [(1<<n)-1]), and there is another problem, which is the printing path, depending on the code.

#include <bits/stdc++.h>
#define ll long long
#define mk make_pair
#define pi pair<int,int>
#define pb push_back
using namespace std;
const int inf = 2e9+100;
struct node {
	int d,f;
	string name;
}a[16];
int dp[16][1<<16],pre[16],n;
int count(int s)
{
	int ans = 0;
	for(int i=0;i<n;i++)if((1<<i&s))ans+=a[i].f;
	return ans;
}
int main()
{
	int T;
	cin>>T;
	while(T--)
	{
		scanf("%d",&n);
		for(int i=0;i<n;i++)cin>>a[i].name>>a[i].d>>a[i].f;
		memset(dp,inf,sizeof(dp));
		for(int i=0;i<n;i++)dp[i][1<<i] = max(0,- a[i].d + a[i].f);
		
		for(int s=1;s<1<<n;s++)
		for(int i=0;i<n;i++)
		if((s&(1<<i))!=0)
		for(int j=0;j<n;j++)
			if((1<<j&s)==0) {
				if(dp[j][s|(1<<j)] > dp[i][s] + max(0 , (count(s)+a[j].f-a[j].d)))
				dp[j][s|(1<<j)] = dp[i][s] + max(0 , (count(s)-a[j].d+a[j].f));
			}
	
		int id=0,ans = inf;
		for(int i=0;i<n;i++)
			if(dp[i][(1<<n)-1] <= ans)
			{
				ans = dp[i][(1<<n)-1];
				id = i;
			}
		cout<<ans<<'\n';
		int sta = (1<<n)-1;
		stack<int>s;
		while(sta)
		{
			s.push(id);
			sta-=(1<<id);
			ans = inf;
			for(int i=0;i<n;i++)
				if(dp[i][sta] <= ans)
				{
					ans = dp[i][sta];
					id = i;
				}
		}
		while(!s.empty())
		{
			cout<<a[s.top()].name<<'\n';
			s.pop();
		}
	}
	return 0;
}

 

Guess you like

Origin blog.csdn.net/weixin_44499508/article/details/105555399