Step1 Problem:
回合制,有n个位置围成一个圈,每个位置上有一个怪(怪有力量值),每回合你可以毁灭掉连续三个位置的怪,回合结束你会受到伤害(剩下怪的力量值的和)。
求消灭所有怪 受到的最少伤害。
数据范围:
3<=N<=20.
Step2 Involving algorithms:
状压DP
Step3 Ideas:
因为N很小,状态压缩后1代表怪没死,0代表怪死了。
初始状态为2^n-1
结束状态为0
记忆化搜索即可
Step4 Code:
#include<bits/stdc++.h>
using namespace std;
const int inf = 0x3f3f3f3f;
int dp[1<<20], a[25], n;
int dfs(int now)
{
// printf("%d\n", now);
if(now == 0) return 0;
if(dp[now] != inf) return dp[now];
for(int i = 0; i < n; i++)
{
if(!(now & (1<<i))) continue;
int nextnow = now;
int hurt = 0;
int l = i-1, r = i+1;//l, i, r连续三个位置
if(i == 0) l = n-1;
if(i == n-1) r = 0;
nextnow = nextnow & (~(1<<i));
nextnow = nextnow & (~(1<<l));
nextnow = nextnow & (~(1<<r));
for(int j = 0; j < n; j++)
{
if(nextnow & (1<<j)) hurt += a[j];//剩下的怪反击的伤害
}
// printf("%d %d\n", nextnow, hurt);
dp[now] = min(dfs(nextnow) + hurt, dp[now]);
}
return dp[now];
}
int main()
{
while(cin >> n)
{
memset(dp, inf, sizeof(dp));
for(int i = 0; i < n; i++)
scanf("%d", &a[i]);
cout << dfs((1<<n)-1) << endl;
}
return 0;
}