拿到这题很容想到去暴力搜索,枚举所有路径去搜索。复杂度为O(n!)显然是不行的
将第i个符串标记为整数数字的第i位,dp[i]表示选取当前字符串最小的花费,如computer为第0位,english为第1位,math为第2位,dp[5]表示dp[101B],即选取computer和math的最小花费,而dp[5]又是由dp[1]和dp[4]更新取最小而来的。这样更新的复杂度为状态数*枚举bit位 = 2^n * n
#include<bits/stdc++.h>
#define pb push_back
#define debug(x) cout<<#x<<" is "<<x<<endl
using namespace std;
int n,m;
const int N = 5e4 + 5;
vector<string> v;
vector<int> deadline,cost;
int dp[N];
int pre[N];
int consumdays[N];
const int INF = 0x3f3f3f3f;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n;
while(n--){
for(int i = 0;i < N;i++){
dp[i] = INF;
pre[i] = 0;
consumdays[i] = 0;
}
dp[0] = 0;
v.clear();
deadline.clear();
cost.clear();
cin>>m;
for(int i = 0;i < m;i++){
string s;
int d,c;
cin>>s>>d>>c;
v.pb(s);
deadline.pb(d);
cost.pb(c);
}
int status = (1<<m);
for(int i = 0;i < status;i++){
int mask = 1;
for(int j = 0;j < m;j++){
if((i&mask) == 0){
int consum = (consumdays[i] + cost[j]) <= deadline[j]?0:(consumdays[i] + cost[j]) - deadline[j];
if(dp[i] + consum < dp[i + mask]){
dp[i + mask] = dp[i] + consum;
pre[i + mask] = i ;
consumdays[i + mask] =cost[j] + consumdays[i];
}
}
mask<<=1;
}
}
cout<<dp[status - 1]<<endl;
vector<int> ans;
int x = status - 1;
while(x != 0){
ans.pb(x - pre[x]);
x = pre[x];
}
for(int i = ans.size() - 1;i >= 0;i--){
int index = 0;
while((ans[i]&1) != 1){
ans[i]>>=1;
index++;
}
cout<<v[index]<<endl;
}
}
return 0;
}