ZOJ3718 Diablo II 狀態壓縮dp

2022-08-18 16:39:15 字數 1653 閱讀 5336

題意:乙個人物有k(k<=7)種技能,每種技能都有bi,ci,di值,表示該技能不能點超過bi次,每點一次加ci,點滿bi次有乙個附加得分di。然後還有n件**,**本身會有能力加成,然後每個**可能會對應著多種的技能,當你裝備了這些**的時候對應的技能的技能點+1(但是**的技能點不能重複,也就是如果a**和b**都能提高技能1的話,如果你兩件都裝備了只算一次)。現在這些都給定給你了,問的是假如現在你有x個技能點(x<=35)和最多不能攜帶超過y件**(y<=100),求你所能獲得的最大的分數。

思維的切入口在於k的數量級是7,一下子就能聯想到2進製的位壓,然後很自然的聯想到了**重複不會增加,所以會選擇定義這麼一種狀態dp[n][y][sta],表示的是前n個物品選了y件達到sta狀態(就是k個技能有沒被加的位壓)的時候所獲得的最大的分數(這裡先不把滿技能點的分算進去)。然後就是for迴圈更新狀態了,n的那一維可以滾動(懶得思考方向了),然後一開始dp[0][0][0]=-1,其他設為-1表示狀態不存在。 dp完後我們就完成了第一項操作了。

現在就是點技能點的時候,點技能點的時候我們怎麼樣才知道最大可以點到多少呢,列舉就可以了!我們定義第二個dps[sta]的陣列,這個表示的是如果當前狀態為sta,那麼我點完技能點的時候所能獲得的最大加成,由於每個bi<=5,所以每次求一次sta最多不需要超過6^7(實際上會小一點),所以求完一遍總是夠時間的。

接下來就是dps[sta]+dp[n&1][y][sta]裡取最大值了(當然不存在的狀態就不要管它了)。

想轉移想了我頗久了- -0

#pragma warning(disable:4996)

#include#include#include#include#include#include#include#define ll long long

#define maxn 120

#define maxk 10

using namespace std;

int k, n;

int b[maxk], c[maxk], d[maxk];

int g[maxn][maxk];

int a[maxn];

int x, y;

int dp[2][maxn][1 << 8];

int dps[1 << 8];

int dfs(int sta, int step, int cnt)

return res;

}int main()

} scanf("%d%d", &x, &y);

memset(dp, -1, sizeof(dp));

dp[0][0][0] = 0;

for (int i = 0; i < n; i++)

}dp[(i + 1) & 1][x + 1][nsta] = max(dp[(i + 1) & 1][x + 1][nsta], dp[i & 1][x][sta] + inc);}}

} for (int i = 0; i < 1 << k; i++)

for (int i = 0; i < 1 << k; i++)

else dps[i] = -1;

} int ans = 0;

for (int i = 0; i < 1 << k; i++)

cout << ans << endl;

} return 0;

}

zoj3755 狀態壓縮dp

很久沒有1a了 爽 題目也是很常規的狀態壓縮題目,這類題目一般都是預處理所有狀態,然後通過列舉,判斷是否符合要求,再從符合要求的末狀態中找到答案即可。這個題目,由於給定的是所有偶數列,那麼,可以想到,每一列只跟左右兩列有關,其他列對其沒有影響。因此,只需要確定了兩列中的一列的狀態,另外一列便可以列舉...

zoj 3471 狀態壓縮dp

題目大意 不超過10種氣體,兩兩之間相互碰撞可以產生一定的能量,如a碰b,那麼b氣體就消失,自身不能碰自身,問最後所能得到的最大能量。題目解析 用10位二進位制表示氣體是否存在,0表示存在,1表示不存在,s 上乙個狀態 中的兩種氣體碰撞並且有一種消失,可以得到news的狀態 狀態轉移 狀態表示 dp...

ZOJ 3802 (狀態壓縮dp)

首先,最樸素的思想為暴搜所有解o 2 n 不可接受 已d i j 代表前 i 個數字 裡 已作出選擇後產生的序列記為 j j 最大為 16,8,4,2全部除以壓縮一下 4000 注意 j 儲存的是乙個序列經產生所屬運算後最後的遞減數數列 舉個栗子 14 8 4 2 當添入 2 變為 16,添入 4 ...