Topcoder Single Round Match 464 Round 1 - Division I, Level Three ColorfulMaze题解

89 篇文章 1 订阅

Topcoder Single Round Match 464 Round 1 - Division I, Level Three ColorfulMaze题解

题面传送门

思路:

这题一看就知道是dp,状态是 d p i , j , m a s k , k dp_{i,j,mask,k} dpi,j,mask,k表示走到 i , j i,j i,j经过了 m a s k mask mask里的颜色,知道哪一个是陷阱,然后从这走到终点的最优概率。

答案为 d p s i , s j , 0 , − 1 dp_{s_i,s_j,0,-1} dpsi,sj,0,1

显然所有的 d p t i , t j , m a s k , k = 1.0 dp_{t_i,t_j,mask,k}=1.0 dpti,tj,mask,k=1.0

然后就考虑转移了:

也不是很难想:
d p i , j , m a s k , k = max ⁡ ( ∑ d p i ′ , j ′ , m a s k ′ , k ′ ∗ P x ) dp_{i,j,mask,k}=\max(\sum dp_{i\prime,j\prime ,mask\prime,k\prime}*P_x) dpi,j,mask,k=max(dpi,j,mask,kPx)
但是我们发现这样转移会出现环,不是很好处理。

但是我们发现环里的dp值都是相同的,所以直接当成一个联通快来做就好了。

代码

/*
{
######################
#       Author       #
#        Gary        #
#        2020        #
######################
*/
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define rb(a,b,c) for(int a=b;a<=c;++a)
#define rl(a,b,c) for(int a=b;a>=c;--a)
#define LL long long
#define IT iterator
#define PB push_back
#define II(a,b) make_pair(a,b)
#define FIR first
#define SEC second
#define FREO freopen("check.out","w",stdout)
#define rep(a,b) for(int a=0;a<b;++a)
#define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define random(a) rng()%a
#define ALL(a) a.begin(),a.end()
#define POB pop_back
#define ff fflush(stdout)
#define fastio ios::sync_with_stdio(false)
#define R(a) cin>>a
#define R2(a,b) cin>>a>>b
#define check_min(a,b) a=min(a,b)
#define check_max(a,b) a=max(a,b)
using namespace std;
const int INF=0x3f3f3f3f;
typedef pair<int,int> mp;
/*}
*/
mp s,t;
int n,final,m,a[51][51];
double dp[51][51][1<<7][8];
int fa[51*51];
double maxi[51*51];
bool vis[51][51];
int root(int x){
	return fa[x]=(fa[x]==x? x:root(fa[x]));
}
void merge(int u,int v){
	u=root(u);
	v=root(v);
	check_max(maxi[v],maxi[u]);
	fa[u]=v;
}
int walk[4][2]={
{0,1},
{-1,0},
{1,0},
{0,-1},
};
class ColorfulMaze{
	public:
	double getProbability(vector<string> maze,vector<int> trap){
		n=maze.size();
		m=maze[0].size();
		rep(i,n)
			rep(j,m)
				a[i+1][j+1]=((maze[i][j]=='$'||maze[i][j]=='.')? -1:((maze[i][j]=='!')? -2:((maze[i][j]=='#')? 30:maze[i][j]-'A')));
		rb(i,1,n)
			rb(j,1,m)
				if(a[i][j]==-2){
						t=II(i,j);
				}
		rb(i,1,n)
			rb(j,1,m)
				if(maze[i-1][j-1]=='$')
					s=II(i,j);
		rb(i,1,n){
			rb(j,1,m) cout<<a[i][j]<<' ';
			cout<<endl;
		}
		final=t.FIR*m+t.second;
		rl(mask,(1<<7)-1,0){
			rep(k,8){
				if(k!=7&&!((mask>>k)&1)) continue;
				rb(i,1,n)
					rb(j,1,m)
						fa[(i-1)*m+j]=(i-1)*m+j;
				int canmask=mask;
				if(k!=7) canmask^=1<<k;
				rb(i,1,n*m)
					maxi[i]=0.0;
				memset(vis,0,sizeof(vis));
				rb(i,1,n)
					rb(j,1,m)
						if(a[i][j]<30)
						if(!vis[i][j]&&(a[i][j]<0||((canmask>>(a[i][j]))&1)))
						{
							
							if(a[i][j]==-2){
								maxi[root((i-1)*m+j)]=1.0;
							}
//							if(mask==1&&k==7){
//								cout<<i<<'-'<<j<<endl;
//							}
							queue<mp> q;
							q.push(II(i,j));
							vis[i][j]=1;
							while(!q.empty()){
								int x,y;
								x=q.front().FIR;
								y=q.front().SEC;
								q.pop();
//								if(mask==1&&k==7)
//								cout<<x<<" "<<y<<endl;
								int nx,ny;
								rep(l,4)
								{
									nx=x+walk[l][0];
									ny=y+walk[l][1];
									if(nx<1||nx>n||ny<1||ny>m) continue;
//									if(mask==1&&k==7)
//									cout<<nx<<'N'<<ny<<endl; 
									if(a[nx][ny]==30) continue;
									if(a[nx][ny]==-2){
										maxi[root((x-1)*m+y)]=1.0;
										merge((x-1)*m+y,(nx-1)*m+ny);
										if(!vis[nx][ny]){
											q.push(II(nx,ny));
											vis[nx][ny]=1;
										}
									} 
									else{
										if(a[nx][ny]==-1||(canmask>>a[nx][ny])&1){
											merge((x-1)*m+y,(nx-1)*m+ny);
											if(!vis[nx][ny]){
												q.push(II(nx,ny));
												vis[nx][ny]=1;
											}
										}
										else{
											if(a[nx][ny]==k) continue;
											int nmask=mask|(1<<a[nx][ny]);
											double P=0.0;
											if(k==7){
												P=(double(trap[a[nx][ny]])/100.0)*dp[nx][ny][nmask][a[nx][ny]]+(double(100.0-trap[a[nx][ny]])/100.0)*dp[nx][ny][nmask][7];
											}
											else{
												P=(double(100.0-trap[a[nx][ny]])/100.0)*dp[nx][ny][nmask][k];
											}
											check_max(maxi[root((x-1)*m+y)],P);
										}
									}
								}
							}									
						}
//				if(mask==0&&k==7){
//					cout<<maxi[root(1)]<<endl;
//				}
				rb(i,1,n)
					rb(j,1,m){
						if(a[i][j]==30) continue;
						if(a[i][j]==-2){
//							cout<<mask<<" "<<k<<' '<<endl;
							dp[i][j][mask][k]=1.0;
							continue;	
						}
						if(a[i][j]==-1||(canmask>>a[i][j])&1){
							dp[i][j][mask][k]=maxi[root((i-1)*m+j)];
						}
						else{
							if(mask>>(a[i][j])&1);
							else continue;
							dp[i][j][mask][k]=0.0;
							rep(l,4)
							{
								int nx,ny;
								nx=i+walk[l][0];
								ny=j+walk[l][1];
								if(nx<1||nx>n||ny<1||ny>m) continue;
								if(a[nx][ny]==30) continue;	
								if(a[nx][ny]==-2){
									dp[i][j][mask][k]=1.0;
									break;
								}
								else{
									if(a[nx][ny]==-1||((canmask>>a[nx][ny])&1)){
										check_max(dp[i][j][mask][k],maxi[root((nx-1)*m+ny)]);
									}
									else{
										if(a[nx][ny]!=k){
											check_max(dp[i][j][mask][k],dp[nx][ny][mask|(1<<a[nx][ny])][k]*(double)(100.0-trap[a[nx][ny]])/100.0);
										}
									}
								}
							}		
						}
					}
			}
		}
//		cout<<t.first<<' '<<t.second<<endl;
//		cout<<dp[4][1][1][7]<<endl; 
//		cout<<dp[1][2][1][7]<<endl;
//		cout<<s.first<<" "<<s.second<<endl;
		return dp[s.FIR][s.second][0][7];
	}
	
}solver;
//int main(){
//	fastio;
//	cout<<solver.getProbability(
//
//
//	
//{ "CC...AA",
//  "C##.##A",
//  "!.E.E.$",
//  "D##.##B",
//  "DD...BB" },
//
//{ 90, 90, 25, 50, 75, 0, 0 }
//
//
//)<<endl;
//	return 0;
//}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值