一开始看题还以为是个贪心,后来仔细看了一下发现并不是,然后发现任务数,就上状压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; }