1152. False Mirrors
Time limit: 2.0 second
Memory limit: 64 MB
Memory limit: 64 MB
Background
We wandered in the labyrinth for twenty minutes before finally entering the large hall. The walls were covered by mirrors here as well. Under the ceiling hung small balconies where monsters stood. I had never seen this kind before. They had big bulging eyes, long hands firmly holding riffles and scaly, human-like bodies. The guards fired at me from the balconies, I shot back using my BFG-9000. The shot shattered three mirrors filling the room with silvery smoke. Bullets drummed against my body-armor knocking me down to the floor. Falling down I let go a shot, and got up as fast as I fell down by rotating on my back, like I did in my youth while break dancing, all this while shooting three more times. Three mirrors, three mirrors, three mirrors…
Sergey Lukjanenko, “The Labyrinth of Reflections”
Problem
BFG-9000 destroys three adjacent balconies per one shoot. (
N-th balcony is adjacent to the first one). After the shoot the survival monsters inflict damage to Leonid (main hero of the novel) — one unit per monster. Further follows new shoot and so on until all monsters will perish. It is required to define the minimum amount of damage, which can take Leonid.
Input
The first line contains integer
N, аmount of balconies, on which monsters have taken a circular defense. 3 ≤
N ≤ 20. The second line contains
N integers, amount of monsters on each balcony (not less than 1 and no more than 100 on each).
Output
Output minimum amount of damage.
Sample
input | output |
---|---|
7 3 4 2 2 1 4 1 | 9 |
Problem Author: Eugene Bryzgalov
Problem Source: Ural Collegiate Programming Contest, April 2001, Perm, English Round
Problem Source: Ural Collegiate Programming Contest, April 2001, Perm, English Round
Difficulty: 175
Printable version
Submit solution
Discussion (30)
All submissions (11122) All accepted submissions (4073) Solutions rating (2390).
All submissions (11122) All accepted submissions (4073) Solutions rating (2390).
题目:有n(n <= 20)个阳台,围成一圈,每个阳台有不同的怪物数,每秒只能杀死一个阳台上的怪物,一个阳台被杀死,则与他相邻的两个阳台也会死亡,但每次幸存的怪物会对其造成相应的伤害,问全部消灭后,最小的伤害值;
思路:状压dp;每个阳台只有两种状态,n<20;
状态 : dp[sta] 表示sta状态下发起攻击后取得的最小伤害值;
状态转移方程 dp[sta] = dp[temp] + damage;
代码:
#include<bits/stdc++.h>
#define ll long long;
using namespace std;
const int maxn = 27;
const int INF = 0x3f3f3f3f;
int a[maxn], dp[1<<21], n;
//dp[sta] :表示sta状态下发起攻击后取得的最小伤害值;
//状态转移方程 dp[sta] = dp[temp] + damage;
int dfs(int sta)
{
if(dp[sta] != INF) return dp[sta];
for(int i = 1; i <= n; i++)
{
if(sta&(1<<(i - 1)))
{
int l, r, temp = sta;
if(i == 1) l = n; else l = i - 1;
if(i == n) r = 1; else r = i + 1;
temp -= 1<<(i - 1);
if(temp & (1<<(l - 1))) temp -= 1<<(l - 1);
if(temp & (1<<(r - 1))) temp -= 1<<(r - 1);
int damage = 0;
for(int j = 1; j <= n; j++) if(temp&(1<<(j - 1))) damage += a[j];
dp[sta] = min(dp[sta], dfs(temp) + damage);
}
}
return dp[sta];
}
int main()
{
//freopen("in.txt", "r", stdin);
while(~scanf("%d", &n))
{
memset(dp, INF, sizeof(dp));
dp[0] = 0;
for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
printf("%d\n", dfs((1<<n) - 1));
}
}