一开始看题还以为是个贪心,后来仔细看了一下发现并不是,然后发现任务数,就上状压dp了,
可以用一个大于0,小于(1<<n)的数字表示做了哪些任务,比如一共有8个任务,数字 的二进制是00100110就表示做了第2,3,6个任务, 表示做了 代表的这些任务的的最小延迟天数。
其实是从以下的三种情况转化来的。



可以发现,转化出dp[i]的情况在数值上都比i小,因为是把i的某一个二进制位变成了0.所以只需要从0开始遍历到(1<<n)-1,推一遍dp值揪可以了。

#include<iostream>
#include<vector>
using namespace std;

const int INF= 0x3f3f3f3f;
int main()
{
    int n;
    cin >> n;
    int deadline[30];
    int cost[30];
    int MAXN = 1<<n;
    int sum = 0;
    for(int i = 0 ; i < n ; i++)
    {
        cin>>deadline[i]>>cost[i];
    }
    vector<int> dp(MAXN,INF);
    dp[0] = 0;
    for(int i = 0 ; i < MAXN ; i++)
    {
        for(int j = 0 ; j < n ; j++)
        {
            if(!(i&(1<<j)))
            {
                int next = i|(1<<j);
                int time = 0;
                for(int k = 0 ; k < n ; k++)
                {
                    if((1<<k)&i)
                    {
                        time+=cost[k];
                    }
                }
                int add = 0;
                dp[next]=min(dp[next],dp[i]+max(0,time+cost[j]-deadline[j]));
            }
        }
    }
    cout<<dp[MAXN-1]<<endl;;
    return 0;
}