任务安排(动态规划)

任务安排(动态规划)_第1张图片
任务安排(动态规划)_第2张图片
解题思路:
采用状态压缩的思路,将每一种状态用二进制数据表示(实际用int类型十进制数据表示,因为n足够小)。从0开始一直遍历到全1,即表示从不选择所有任务增加到选择所有的任务,每一种情况单独考虑。dp状态f[s]即表示对应于状态s的最小值即答案。注意没有答案为-1所以对f数组初始化为-1,f[0]=0(表示不选择任何任务进行完成)。dp状态转移方程为:
任务安排(动态规划)_第3张图片
另外,为了保证字典序最小,只有当之后的dp值严格大于当前dp值时才对dp进行更新。
参考代码:

#include 
#include 
#include 
#include 
using namespace std;
int t,n;
int f[1<<15];
int pre[1<<15];
int sum[1<<15];
struct assignment{
    string str;
    int d,c;
    assignment(string s="",int x=0,int y=0):str(s),d(x),c(y){}
}a[20];
int main(int argc, const char * argv[]) {
    cin>>t;
    while (t--) {
        cin>>n;
        for (int i=0; i<n; i++) {
            cin>>a[i].str>>a[i].d>>a[i].c;
        }
        memset(f, -1, sizeof(f));
        memset(pre, 0, sizeof(pre));
        memset(sum, 0, sizeof(sum));
        f[0]=0;
        for (int s=0; s<(1<<n); s++) {//遍历每一种状态
            for (int i=0; i<n; i++) {
                if(!(s&(1<<i)))//不包含i
                {
                    int tmp=sum[s]+a[i].c-a[i].d>0?sum[s]+a[i].c-a[i].d:0;
                    if(f[s|(1<<i)]>f[s]+tmp||f[s|(1<<i)]==-1){
                        f[s|(1<<i)]=f[s]+tmp;
                        pre[s|(1<<i)]=i;
                        sum[s|(1<<i)]=sum[s]+a[i].c;
                    }
                }
            }
        }
        int s=(1<<n)-1;
        cout<<f[s]<<endl;
        vector<string> v;
        while (s!=0) {
            v.push_back(a[pre[s]].str);
            s=s^(1<<pre[s]);
        }
        for (int i=(int)v.size()-1; i>=0; i--) {
            cout<<v[i]<<endl;
        }
        
    }
    return 0;
}

你可能感兴趣的:(任务安排(动态规划))