题意:
给出n<=20种病毒的潜伏期D<=7,每天只能注射一种病毒,也只能检测一次,只有体内有一种病毒的时候才能被检测出类型,求检测所有病毒需要的最短时间
分析:
我们发现是否注入新的病毒跟之前的病毒有关系,需要知道何时注入新的
发现只要记录上一个病毒能帮我们减少的等待时间就好了
dp[left][s]:=上一个病毒剩余的减少的等待的时间,当前未测试的病毒状态为s,到终态需要的最短时间
转移就跟a[i]比一下,大的话,剩余时间变成a[i]−left−1,多减1因为留一天测自己,然后时间多了a[i]−left,这种状态一定不是最优的终止状态,因为我还能套
不然就转移到,剩余时间为0,时间多了1天
画个重叠图,这题很水,最多剩余6天,复杂度O(n∗D∗2n)
代码:
//
// Created by TaoSama on 2015-11-24
// Copyright (c) 2015 TaoSama. All rights reserved.
//
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>
using namespace std;
#define pr(x) cout << #x << " = " << x << " "
#define prln(x) cout << #x << " = " << x << endl
const int N = 1e5 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;
int n, a[20], dp[7][1 << 20];
int dfs(int left, int s) {
int &ret = dp[left][s];
if(!s) return 0;
if(~ret) return ret;
ret = INF;
for(int i = 0; i < n; ++i) {
if(!(s >> i & 1)) continue;
if(a[i] > left)
ret = min(ret, dfs(a[i] - left - 1, s ^ (1 << i)) + a[i] - left);
else
ret = min(ret, dfs(0, s ^ (1 << i)) + 1);
}
return ret;
}
int main() {
#ifdef LOCAL
freopen("C:\\Users\\TaoSama\\Desktop\\in.txt", "r", stdin);
// freopen("C:\\Users\\TaoSama\\Desktop\\out.txt","w",stdout);
#endif
ios_base::sync_with_stdio(0);
int t; scanf("%d", &t);
while(t--) {
scanf("%d", &n);
for(int i = 0; i < n; ++i) scanf("%d", a + i);
memset(dp, -1, sizeof dp);
printf("%d\n", dfs(0, (1 << n) - 1));
}
return 0;
}