UVA 11691 - Allergy Test(状压dp+贪心)

来源:互联网 发布:张孝祥java视频 编辑:程序博客网 时间:2024/05/22 08:18

题目链接:11691 - Allergy Test

题意:这题题意看了老半天都没弄懂,好在后面找到个PPT,上面有中文题意- -,不过上面的做法是纯贪心,挺巧妙的但是感觉有点不靠谱,
下载地址:http://par.cse.nsysu.edu.tw/~advprog/advprog2011/11691.ppt
N種過敏原的存活期,每天可把一種過敏原注入人體內。若有兩個以上過敏原存活於人體中,則無法進行實驗(也就是每種過敏原都必須有一天是單獨存活於人體中)。實驗結束於最後的過敏原死亡的那天,求最短實驗天數。
思路:我的思路是状态压缩dp+贪心,20个过敏原做状态压缩,然后每次加过敏原的时候,尽量往里面覆盖,dp[s][k],s表示过敏原使用状态,k表示后面通出来单独存在过敏原的天数,然后选一个新的过敏原去尽量覆盖他,这样k的一维只要开到7就够了,因为每段长度最多就是7。状态转移方程为:
dp[k][s] = min{dfs(s^(1<<i), max(0, num[i] - k - 1)) + max(1, num[i] - k)}
代码:
#include <stdio.h>#include <string.h>#include <map>#include <algorithm>using namespace std;#define INF 0x3f3f3f3f#define min(a,b) ((a)<(b)?(a):(b))#define max(a,b) ((a)>(b)?(a):(b))const int N = 25;const int M = (1<<20) + 5;int t, n, num[N], dp[M][8];int dfs(int s, int k) {    if (dp[s][k] != -1) return dp[s][k];    dp[s][k] = INF;    if (s == (1<<n) - 1) return dp[s][k] = 0;int vis[8];memset(vis, 0, sizeof(vis));    for (int i = 0; i < n; i++) {if (vis[num[i]]) continue;        if (s&(1<<i)) continue;vis[num[i]] = 1;        int t = dfs(s^(1<<i), max(0, num[i] - k - 1)) + max(1, num[i] - k);        dp[s][k] = min(dp[s][k], t);    }    return dp[s][k];}int main() {    scanf("%d", &t);    while (t--) {        scanf("%d", &n);memset(dp, -1, sizeof(dp));        for (int i = 0; i < n; i++)            scanf("%d", &num[i]);        printf("%d\n", dfs(0, 0));    }    return 0;}


1 0
原创粉丝点击