福大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......*
***********.*
*...#.*...*.*
*************
*/



【洛谷2017年3月月赛】Round1第四题-环套树森林DFS+贪心

【洛谷2017年3月月赛】Round1第四题-环套树森林DFS+贪心
  • Maxwei_wzj
  • Maxwei_wzj
  • 2017年03月12日 22:35
  • 175

4831: [Lydsy2017年4月月赛]序列操作

4831: [Lydsy2017年4月月赛]序列操作Time Limit: 1 Sec Memory Limit: 128 MB Submit: 77 Solved: 33 [Submit][...
  • CRZbulabula
  • CRZbulabula
  • 2017年05月29日 20:46
  • 330

【ZOJ3921 2016年浙大2月月赛L】【随机化 答案猜解】Parity Modulo P 大数mod大数mod2

Parity Modulo P Time Limit: 2 Seconds      Memory Limit: 131072 KB A Mersenne prime is a prime...
  • snowy_smile
  • snowy_smile
  • 2016年03月01日 18:07
  • 926

2015年NEUACM一月月赛

2015年NEUACM一月月赛 J 问题 J: Eliminate zero AC 时间限制: 1 Sec  内存限制: 128 MB 提交: 332  解决: 131 [提交][状态][讨论版]...
  • Enjoying_Science
  • Enjoying_Science
  • 2015年02月10日 22:59
  • 657

4833: [Lydsy2017年4月月赛]最小公倍佩尔数 数论变换

先吐槽一下:唐老师下标全崩了,最重要的后面的一坨推导全都挂了qwq,我推到倒数第二步然后和题解一对发现我好想全推错了233333? 最后还是找的A了的zyz才弄明白他写的是什么这题和一道斐波那契公倍数...
  • qq_32451161
  • qq_32451161
  • 2017年06月27日 18:34
  • 305

CodePlus 2017 12 月赛 火锅盛宴 线段树+离线

题意 分析先离线把每个时刻有哪些食物从不熟变熟。开一棵线段树记录当前时刻每种食物有多少个是熟的。 对每种食物开一棵以时间轴为下标的线段树记录在每个时刻还有多少种食物。 在到达一个时刻时先把在该时...
  • qq_33229466
  • qq_33229466
  • 2017年12月25日 21:51
  • 88

杭电OJ -- 2034 人见人爱A-B(c++练手的好题目)

人见人爱A-B Problem Description 参加过上个月月赛的同学一定还记得其中的一个最简单的题目,就是{A}+{B},那个题目求的是两个集合的并集,今天我们这个A-B求的是两个集合的...
  • lishuhuakai
  • lishuhuakai
  • 2015年10月04日 11:39
  • 2088

sdjzu百题训练--人见人爱A-B

E - 人见人爱A-B Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Submit St...
  • hy1405430407
  • hy1405430407
  • 2015年01月15日 22:15
  • 1097

赛风3-带病毒版安卓App分析报告

0x00 前言0.1 关键字手机自动下载游戏到 手机解锁后提示安装软件 /sdcard/system/download 赛风病毒 如果你的手机内存卡有sdcard/system/32、sdca...
  • pingfangx
  • pingfangx
  • 2016年07月22日 16:57
  • 4168

nyist14年3月月赛题解

比赛链接: http://acm.bnu.edu.cn/bnuoj/contest_show.php?cid=3475#info 比较没状态,成绩不算好。题目有很水,都是靠脑子的。 旅游 Ti...
  • y990041769
  • y990041769
  • 2014年03月08日 19:44
  • 2952
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:福大3月月赛 魔塔
举报原因:
原因补充:

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