福大3月月赛 魔塔

原创 2012年03月30日 16:03:18

转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents           by---cxlove

http://acm.fzu.edu.cn/problem.php?pid=2073

又是一个神题,给出一个n*m的图,上面有若干个怪,每个怪有一定的血,攻击,防御,以及攻击奖励,防御奖励。
玩过魔塔的童鞋应该很清楚,每打一个怪,消灭他,可以获得一定的攻击防御奖励,消灭所有的怪,就算成功了。
此题是外挂摸式,无限血,不过也存在无法过关的情况,求消灭所有的怪,受到的最少伤害。
想当年cxlove通关救出了公主,哈哈。
处理起来很麻烦,首先枚举所有的怪为起点,bfs找可以到达的其它怪,邻接阵保存。

之后是状态DP,dp[i][j],表示当前位置为i,当前状态为j。


/*
ID:cxlove
PROB:FJU2073魔塔
DATA:2012.3.27-3.28
HINT:bfs+状态DP
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#define inf 1<<30
using namespacestd;
struct Node{
    inthp,attack,defense,award_attack,award_defense;
    //怪的血量,攻击,防御,攻击奖励,防御奖励
}monster[11];
struct Point{
    int x,y;
}s,que[500*500+10];
struct Monster{
    Point pos;
    int kind; 
    //记录地图上怪兽的位置和怪物种类
}Map[11];
char str[505][505];
int cnt;//怪兽的个数
int n,m,p;
int mat[15][15];
bool flag[505][505];
int way[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
int dp[11][1<<10]; //dp[i][j]表示目前处在第i个怪物的位置,已杀怪物的状态为j时的最少伤害
void bfs(int k){
    Point p;
    inthead=0,tail=0;
    que[tail++]=Map[k].pos;
    flag[que[0].x][que[0].y]=true;
    while(head<tail){
        p=que[head++];     
        for(int i=0;i<4;i++){
            Point pp;
            pp.x=p.x+way[i][0];
            pp.y=p.y+way[i][1];
            if(str[pp.x][pp.y]!='*'&&pp.x>=0&&pp.x<n&&pp.y>=0&&pp.y<m&&flag[pp.x][pp.y]==false){
                if(str[pp.x][pp.y]=='.')
                    que[tail++]=pp;
                else{
                   for(int j=1;j<=cnt;j++)
                        if(pp.x==Map[j].pos.x&&pp.y==Map[j].pos.y)
                            mat[k][j]=1;
                }
                flag[pp.x][pp.y]=true;
            }
        }
    }
}
int check(int state,int k){
    intper_attack=10,per_deffense=10;
    //初始攻击,防御
    for(int i=0;i<cnt;i++)
        if((1<<i)&state){
            intkind=Map[i+1].kind;
            per_attack=min(50,monster[kind].award_attack+per_attack);
            per_deffense=min(50,monster[kind].award_defense+per_deffense);
        }  
    intkind=Map[k].kind;
   /*cout<<per_attack<<""<<per_deffense<<endl;*/
    if(per_attack<=monster[kind].defense)
        return-1;
    if(per_deffense>=monster[kind].attack)
        return0;
    inthp=monster[kind].hp,a1=per_attack,d1=monster[kind].defense,a2=monster[kind].attack,d2=per_deffense;
    return(hp/(a1-d1)+(hp%(a1-d1)==0?-1:0))*(a2-d2);
}
int sum[1<<10];
vector<int>status[11];
int main(){
    sum[0]=0;
    for(int i=1;i<(1<<10);i++){
        sum[i]=sum[i>>1]+(i&1);
        status[sum[i]].push_back(i);
    }
    while(scanf("%d%d%d",&n,&m,&p)!=EOF){
        cnt=0;
        for(int i=1;i<=p;i++)
            scanf("%d%d%d%d%d",&monster[i].hp,&monster[i].attack,&monster[i].defense,&monster[i].award_attack,&monster[i].award_defense);
        for(int i=0;i<n;i++){
            scanf("%s",str[i]);
            for(int j=0;j<m;j++)
                if(str[i][j]=='#'){
                    s.x=i;
                    s.y=j;
                }
                elseif(str[i][j]>='1'&&str[i][j]<='9'){
                    cnt++;
                    Map[cnt].pos.x=i;
                    Map[cnt].pos.y=j;
                    Map[cnt].kind=str[i][j]-'0';
                }
        }
        Map[0].pos=s;Map[0].kind=0;
        memset(mat,0,sizeof(mat));
        for(int i=0;i<=cnt;i++){
            memset(flag,false,sizeof(flag));
            bfs(i);
        }
        /*for(inti=0;i<=cnt;i++){
            for(int j=0;j<=cnt;j++)
                printf("%d  ",mat[i][j]);
            printf("\n");
        }*/
        for(int i=0;i<=cnt;i++)
            for(int j=0;j<(1<<cnt);j++)
                dp[i][j]=inf;
        dp[0][0]=0;
        for(int i=1;i<=cnt;i++){
            if(mat[0][i]){
                inttemp=check(0,i);
                if(temp<0)
                    continue;
                dp[i][1<<(i-1)]=temp;
            }
        }
        /*for(inti=1;i<=cnt;i++)
           if(dp[i][1<<(i-1)]!=inf)
                printf("%d%d\n",i,dp[i][1<<(i-1)]);*/
        for(int i=1;i<cnt;i++){
            for(int j=0;j<status[i].size();j++){
               intJ=status[i][j];
                for(int k=1;k<=cnt;k++){               
                    //dp[k][J]
                    if(((1<<(k-1))&J)&&dp[k][J]!=inf){
                        for(int r=1;r<=cnt;r++){
                            if(mat[k][r]&&k!=r&&((1<<(r-1))&J)==0){                        
                                int temp=check(J,r);                           
                                /*cout<<k<<" "<<J<<""<<r<<" "<<temp<<endl;
                                system("pause");*/
                                if(temp<0)
                                    continue;                          
                                dp[r][J|(1<<(r-1))]=min(dp[r][J|(1<<(r-1))],dp[k][J]+temp);
                                for(intrr=1;rr<=cnt;rr++)//注意!!!BFS的时候状态是在原图未消灭一个怪的前提下,注意更新后的情况
                                    if(J&(1<<(rr-1)))
                                        dp[rr][J|(1<<(r-1))]=min(dp[rr][J|(1<<(r-1))],dp[r][J|(1<<(r-1))]);
                            }
                        }
                    }
                }
            }
        }
        int ans=inf;
        for(int i=1;i<=cnt;i++)
            ans=min(ans,dp[i][(1<<cnt)-1]);
        if(ans==inf)
            printf("-1\n");
        else
            printf("%d\n",ans);
    }
    return 0;
}
/*
1313 6
1012 2 2 1
202 2 2 3
3013 3 1 1
4014 4 1 1
5011 5 1 1
6028 6 1 1
*************
*..121......*
***********.*
*.....*...*.*
*.5.*.*...*.*
**.**.***.*.*
*...*..343*.*
*.6.*.*****.*
**.**.......*
*...**.***.**
*...*...*.3.*
*...*.#.*1..*
*************
513 2
1012 2 2 1
202 2 2 3
*************
*..121......*
***********.*
*...#.*...*.*
*************
*/



相关文章推荐

(福大2015年3月月赛)FZU 2186 小明的迷宫 (BFS+状压DP)

题目地址:FZU 2186 这题是很基础的TSP状压,各个点之间的距离要先用BFS预处理出来。 这题在写memset(dp,INF,sizeof(dp));时,写成了memset(dp,INF,s...

(福大2015年3月月赛)FZU 2185 树的路径覆盖 (DFS)

题目地址:FZU 2185 允许重复覆盖的值比较好求,一条路径覆盖两个叶子节点,所以答案是(叶子结点数+1)/2。至于不允许重复覆盖的,我第一次想的是叶子节点数-1,因为先让第一条覆...

浙大2014 3月月赛I题(伸展树)

模板: #include #include #include #define ll long long using namespace std ; const int maxn = 500011 ...

福大计算机图形学考试模拟题3

  • 2015年11月06日 22:20
  • 154KB
  • 下载

nyist14年3月月赛题解

比赛链接: http://acm.bnu.edu.cn/bnuoj/contest_show.php?cid=3475#info 比较没状态,成绩不算好。题目有很水,都是靠脑子的。 旅游 Ti...

cocos2d-x实例-魔塔游戏(3)-控制勇士行走

本文在上节的基础上,在地图加上可以行走的勇士 。 勇士可以被视为一个精灵(CCSprite),它包含上、下、左、右4个方向的行走动作,如下图 将上图保存为hero.png,放到Reso...

ZOJ3686____ZOJ 2013年3月月赛第一题(先序遍历+线段树)

题目地址:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4969 首先想说的是这题可以充分说明自己太菜了。看来自己还要继续学习...
  • dr5459
  • dr5459
  • 2013年04月01日 17:11
  • 1104

4886: [Lydsy2017年5月月赛]叠塔游戏

4886: [Lydsy2017年5月月赛]叠塔游戏Time Limit: 20 Sec Memory Limit: 256 MB Submit: 124 Solved: 40 [Submit...

中南大学2012年8月月赛 B题 Barricade

Problem B: Barricade Time Limit: 1 Sec  Memory Limit: 32 MB SUBMIT: 185  Solved: 47 [SUBMIT][STAT...

2017年5月月赛-暨中南大学暑期集训选拔赛第一场-部分题目

1.1924: 那些年寮里的崽儿们 题目 1924: 那些年寮里的崽儿们 分析 用Java来做的话,其实这道题可以用一个LinkedHashMap来保存输入的字符串和它出现的次数,因为Linked...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:福大3月月赛 魔塔
举报原因:
原因补充:

(最多只允许输入30个字)