蒜头君救人
来源:互联网 发布:德文布克体测数据 编辑:程序博客网 时间:2024/04/27 23:00
https://nanti.jisuanke.com/t/16444
算法 1
对于 10%10\%10% 的数据,发现只有一个村民需要救,直接 BFS 搜索即可,期望得分 101010 分。
算法 2
设村民个数为 numnumnum,用dp[2num][2num][n][m]dp[2^{num}][2^{num}][n][m]dp[2num][2num][n][m] 来表示如下信息:
第一维每一位若为 111 表示该村民正被蒜头君所背,第二维每一位若为1表示该村民已被放至安全地带,最后两维表示蒜头君当前所处位置。
转移时只需考虑当前点是否有村民和是否是安全地带,以及可以往哪个方向移动即可。
时间复杂度 O(4numNM)\mathcal{O}(4^{num}NM)O(4numNM),期望得分505050 分。
算法 3
将前两维改用一个三进制数来储存,每一位若为 000 代表村民还在原地,为 111 代表村民正被蒜头君背着,为 222 代表村民已到达终点。时间复杂度 O(3numNM)\mathcal{O}(3^{num}NM)O(3numNM),期望得分100100100 分。
#include<bits/stdc++.h>using namespace std;int n,m,k,t,sx,sy,tx,ty;char mp[25][25],s[15][3];int sp[15],st[15];int dp[60000][25][25],Pow[15];int q[24000000][3];int cal_spd(int x){for(int i=1;i<=t;i++) st[i]=0;int tmp=0;while(x){tmp++;st[tmp]=x%3;x/=3;}int ans=k;for(int i=1;i<=t;i++)if(st[i]==1) ans+=sp[i];if(ans<1) ans=1;return ans;}int pick(int num,int x,int y){for(int i=1;i<=t;i++) st[i]=0;int tmp=0;while(num){tmp++;st[tmp]=num%3;num/=3;}int nu=0;for(int i=1;i<=t;i++) if(s[i][0]==mp[x][y]) nu=i;if(st[nu]) return 0;st[nu]=1;for(int i=t;i>=1;i--){num=num*3+st[i];}return num;}int drop1(int x){for(int i=1;i<=t;i++) st[i]=0;int tmp=0;while(x){tmp++;st[tmp]=x%3;x/=3;}for(int i=1;i<=t;i++)if(st[i]==1&&sp[i]>0) st[i]=2;for(int i=t;i>=1;i--){x=x*3+st[i];}return x;}int drop2(int x){for(int i=1;i<=t;i++) st[i]=0;int tmp=0;while(x){tmp++;st[tmp]=x%3;x/=3;}for(int i=1;i<=t;i++)if(st[i]==1) st[i]=2;for(int i=t;i>=1;i--){x=x*3+st[i];}return x;}int main(){scanf("%d%d%d",&n,&m,&k);for(int i=1;i<=n;i++) scanf("%s",mp[i]+1);for(int i=1;i<=n;i++)for(int j=1;j<=m;j++){if(mp[i][j]=='s') sx=i,sy=j;if(mp[i][j]=='t') tx=i,ty=j;if(mp[i][j]>='A'&&mp[i][j]<='Z') t++;}//cout<<t<<endl;Pow[0]=1;for(int i=1;i<=t;i++)Pow[i]=Pow[i-1]*3;for(int i=1;i<=t;i++)scanf("%s%d",s[i],&sp[i]);memset(dp,127,sizeof(dp));dp[0][sx][sy]=0;q[0][0]=0,q[0][1]=sx,q[0][2]=sy;int head=0,tail=0;//cout<<cal_spd(3)<<endl;while(head<=tail){int now=head;head++;int nx=q[now][1],ny=q[now][2],nst=q[now][0];//cout<<nst<<' '<<nx<<' '<<ny<<' '<<dp[nst][nx][ny]<<endl;int spd=cal_spd(nst);//cout<<spd<<endl;if(nx+1<=n&&mp[nx+1][ny]!='#'&&dp[nst][nx+1][ny]>dp[nst][nx][ny]+spd) {dp[nst][nx+1][ny]=dp[nst][nx][ny]+spd;tail++;q[tail][0]=nst,q[tail][1]=nx+1,q[tail][2]=ny;}if(ny+1<=m&&mp[nx][ny+1]!='#'&&dp[nst][nx][ny+1]>dp[nst][nx][ny]+spd) {dp[nst][nx][ny+1]=dp[nst][nx][ny]+spd;tail++;q[tail][0]=nst,q[tail][1]=nx,q[tail][2]=ny+1;}if(nx-1>0&&mp[nx-1][ny]!='#'&&dp[nst][nx-1][ny]>dp[nst][nx][ny]+spd) {dp[nst][nx-1][ny]=dp[nst][nx][ny]+spd;tail++;q[tail][0]=nst,q[tail][1]=nx-1,q[tail][2]=ny;}if(ny-1>0&&mp[nx][ny-1]!='#'&&dp[nst][nx][ny-1]>dp[nst][nx][ny]+spd) {dp[nst][nx][ny-1]=dp[nst][nx][ny]+spd;tail++;q[tail][0]=nst,q[tail][1]=nx,q[tail][2]=ny-1;}if(mp[nx][ny]>='A'&&mp[nx][ny]<='Z'){int nxst=pick(nst,nx,ny);if(nxst&&dp[nxst][nx][ny]>dp[nst][nx][ny]){dp[nxst][nx][ny]=dp[nst][nx][ny];tail++;q[tail][0]=nxst,q[tail][1]=nx,q[tail][2]=ny;}}if(mp[nx][ny]=='t') {int nxst1=drop1(nst),nxst2=drop2(nst);if(dp[nxst1][nx][ny]>dp[nst][nx][ny]){dp[nxst1][nx][ny]=dp[nst][nx][ny];tail++;q[tail][0]=nxst1,q[tail][1]=nx,q[tail][2]=ny;}if(dp[nxst2][nx][ny]>dp[nst][nx][ny]){dp[nxst2][nx][ny]=dp[nst][nx][ny];tail++;q[tail][0]=nxst2,q[tail][1]=nx,q[tail][2]=ny;}}}//cout<<head<<' '<<tail<<endl;printf("%d\n",dp[Pow[t]-1][tx][ty]);}
阅读全文
0 0
- 蒜头君救人
- 蒜头君救人 状压DP
- 蒜头君的树
- 蒜头君吃桃子
- 蒜头君打老鼠
- 蒜头君的树
- 蒜头君的坐骑
- 蒜头君的兔子
- 蒜头君的排序
- 计蒜课 蒜头君走迷宫
- 计蒜客 蒜头君学英语
- 蒜头君的玩具娃娃
- 蒜头君开公司【全排列】
- 计蒜客 蒜头君的随机数,造房子
- 蒜头君学代数(二分)
- 基础算法之“蒜头君采摘苹果”
- 蒜头君学英语--set()练习
- 二叉搜索树之蒜头君的新技能
- android popupwindow
- 设备兼容性
- 老男孩14期14周作业-简单的商城页面布局
- 在 Oracle JDBC 访问中加入一些 Spring 特性
- C#文件夹加锁小工具
- 蒜头君救人
- S01E02 Selenium Webdriver自动化编程初步(上)
- jaxb xml转javaBean
- 两个数的运算,结果保留n位有效数字,不足补0。
- LintCode:两个整数相除
- jquery基本选择器:id选择器、class选择器、标签选择器、通配符选择器
- oracle OCP认证
- POJ2430 Lazy Cows【状压DP+离散化】
- 网易2017实习生招聘笔试题编程题参考思路和代码