Codeforces Beta Round #6 (Div. 2 Only) D. Lizards and Basements 2 dp

题目链接:

http://codeforces.com/problemset/problem/6/D

D. Lizards and Basements 2

time limit per test2 seconds
memory limit per test64 megabytes
#### 问题描述 > This is simplified version of the problem used on the original contest. The original problem seems to have too difiicult solution. The constraints for input data have been reduced. > > Polycarp likes to play computer role-playing game «Lizards and Basements». At the moment he is playing it as a magician. At one of the last levels he has to fight the line of archers. The only spell with which he can damage them is a fire ball. If Polycarp hits the i-th archer with his fire ball (they are numbered from left to right), the archer loses a health points. At the same time the spell damages the archers adjacent to the i-th (if any) — they lose b (1 ≤ b < a ≤ 10) health points each. > > As the extreme archers (i.e. archers numbered 1 and n) are very far, the fire ball cannot reach them. Polycarp can hit any other archer with his fire ball. > > The amount of health points for each archer is known. An archer will be killed when this amount is less than 0. What is the minimum amount of spells Polycarp can use to kill all the enemies? > > Polycarp can throw his fire ball into an archer if the latter is already killed.

输入

The first line of the input contains three integers n, a, b (3 ≤ n ≤ 10; 1 ≤ b < a ≤ 10). The second line contains a sequence of n integers — h1, h2, ..., hn (1 ≤ hi ≤ 15), where hi is the amount of health points the i-th archer has.

输出

In the first line print t — the required minimum amount of fire balls.

In the second line print t numbers — indexes of the archers that Polycarp should hit to kill all the archers in t shots. All these numbers should be between 2 and n - 1. Separate numbers with spaces. If there are several solutions, output any of them. Print numbers in any order.

样例输入

3 2 1
2 2 2

样例输出

3
2 2 2

题意

现在有n个弓箭手从1到n排成一排,每个人有hi的血量,你只能用火球术去杀死他们,如果你对第i个人使用火球术,将对他造成a点伤害,并且对i-1,i+1造成b点的火焰伤害,你不能直接打第1个和第n个人,问至少需要使用多少次火球术能杀死所有的弓箭手。

题解

首先想到把每人的血量作为状态,这样状态是15^10,QAQ。
正解:dp[i][j][k][l]代表,你现在打算打第i个人,且第i-1个人的血量为j,第i个人的血量为k,第i+1个人的血量为l。
dp[1][h[0]][h[1]][h[2]]=0.

代码

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<ctime>
#include<vector>
#include<cstdio>
#include<string>
#include<bitset>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
using namespace std;
#define X first
#define Y second
#define mkp make_pair
#define lson (o<<1)
#define rson ((o<<1)|1)
#define mid (l+(r-l)/2)
#define sz() size()
#define pb(v) push_back(v)
#define all(o) (o).begin(),(o).end()
#define clr(a,v) memset(a,v,sizeof(a))
#define bug(a) cout<<#a<<" = "<<a<<endl
#define rep(i,a,b) for(int i=a;i<(b);i++)
#define scf scanf
#define prf printf

typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
typedef vector<pair<int,int> > VPII;

const int INF=0x3f3f3f3f;
const LL INFL=10000000000000000LL;
const double eps=1e-9;

const double PI = acos(-1.0);

//start----------------------------------------------------------------------

int dp[15][20][20][20];
int v[15];
int n,a,b;

struct Node{
    int i,j,k,l;
    bool operator == (const Node& tmp){
        return i==tmp.i&&j==tmp.j&&k==tmp.k&&l==tmp.l;
    }
    Node(int i,int j,int k,int l):i(i),j(j),k(k),l(l){}
    Node(){}
}pre[15][20][20][20];

int main() {
    scf("%d%d%d",&n,&a,&b);
    for(int i=0;i<n;i++){
        scf("%d",&v[i]);
        v[i]++;
    }

    clr(dp,0x3f);
    int INF=dp[0][0][0][0];
    dp[1][v[0]][v[1]][v[2]]=0;

    for(int i=1;i<n-1;i++){
        for(int j=v[i-1];j>=0;j--){
            for(int k=v[i];k>=0;k--){
                for(int l=v[i+1];l>=0;l--){
                    if(dp[i][j][k][l]>=INF) continue;

                    if(j==0&&dp[i+1][k][l][v[i+2]]>dp[i][j][k][l]){
                        dp[i+1][k][l][v[i+2]]=dp[i][j][k][l];
                        pre[i+1][k][l][v[i+2]]=pre[i][j][k][l];
                    }

                    int nj=max(0,j-b);
                    int nk=max(0,k-a);
                    int nl=max(0,l-b);

                    if(dp[i][nj][nk][nl]>dp[i][j][k][l]+1){
                        dp[i][nj][nk][nl]=dp[i][j][k][l]+1;
                        pre[i][nj][nk][nl]=Node(i,j,k,l);
                    }

                    if(nj==0&&dp[i+1][nk][nl][v[i+2]]>dp[i][j][k][l]+1){
                        dp[i+1][nk][nl][v[i+2]]=dp[i][j][k][l]+1;
                        pre[i+1][nk][nl][v[i+2]]=Node(i,j,k,l);
                    }

                }
            }
        }
    }

    prf("%d\n",dp[n-2][0][0][0]);

    Node tmp=pre[n-2][0][0][0];

    while(1){
        prf("%d ",tmp.i+1);
        if(tmp==Node(1,v[0],v[1],v[2])) break;
        tmp=pre[tmp.i][tmp.j][tmp.k][tmp.l];
    }

    return 0;
}

//end-----------------------------------------------------------------------
posted @ 2016-10-31 22:02  fenicnn  阅读(148)  评论(0编辑  收藏  举报