zoukankan      html  css  js  c++  java
  • 洛谷 P3786 萃香抱西瓜

    P3786 萃香抱西瓜 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)(题面太长了,复制过来很麻烦)

    他看上去像一个状压dp,而且t,h,w,m的范围都很小,就直接设计一个dp[i][x][y][f]表示在第i秒,角色位置在(x,y),目前抱西瓜的状态为f时最少要走的步数。

    然后可以发现t只能向t+1转移,符合DAG的性质,可以放心打dp,但是每次遍历还需要判断能不能走,似乎很麻烦(?

    (突然发现可以预处理每个时间点的每个位置能不能到达)

    定义一个数组can[t][x][y]表示t时间时(x,y)能不能到达,还有一个flag[t][x][y]数组表示在t时间时在(x,y)的西瓜编号

    (注意转移的时候不要漏判可以原地不动的情况,还有dp的初始化,如果一开始在出发点有小西瓜是要初始化进去的)

    (dp的转移方程在代码里看吧)

    可能全分有点困难,下面还有部分分的得分方法(如果我能看出来的话之后的博客都会有):

    子任务 1:所有西瓜静止,且不需要捡任何一个

    做法:直接判断初始位置有没有大西瓜即可

    子任务 2~3:所有西瓜静止,需要捡小于10个西瓜

    做法:因为需要捡的数量最多只有10个,而且不动,可以直接状压跑最短路或者dp求解

    子任务4~5:西瓜会运动,不需要捡西瓜

    做法:按时间将图分层,然后跑最短路或者dp

    子任务1~10:(最开始)

    代码:

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    long long h,w,t,sx,sy,n,m;
    long long dp[105][6][6][1<<10+1];
    inline long long read(){
    	long long s=0,f=1;
    	char c=getchar();
    	while(!isdigit(c)){
    		if(c=='-'){
    			f=-f;
    		}
    		c=getchar();
    	}
    	while(isdigit(c)){
    		s=(s<<3)+(s<<1)+(c^48);
    		c=getchar();
    	}
    	return s*f;
    }
    long long can[105][6][6],flag[105][6][6];
    int main(){
    	memset(dp,0x3f,sizeof(dp));
    	h=read();
    	w=read();
    	t=read();
    	sx=read();
    	sy=read();
    	for(int i=1;i<=t;i++){
    		for(int j=1;j<=h;j++){
    			for(int k=1;k<=w;k++){
    				can[i][j][k]=1;
    			}
    		}
    	}
    	n=read();
    	m=read();
    	long long wz=0,tm1=0,tm2=0,x,y,ok=0;
    	for(int i=1;i<=n;i++){
    		tm1=read();
    		tm2=read();
    		ok=read();
    		if(ok==1){
    			wz++;
    			for(int j=tm1;j<tm2;j++){
    				x=read();
    				y=read();
    				flag[j][x][y]=wz;
    			}
    		}else
    		{
    			for(int j=tm1;j<tm2;j++){
    				x=read();
    				y=read();
    				can[j][x][y]=0;
    			}
    		}
    	}
    	if(can[1][sx][sy]==0){
    		cout<<-1<<endl;
    	}
    	if(flag[1][sx][sy]!=0){
    		dp[1][sx][sy][1<<(flag[1][sx][sy]-1)]=0;
    	}else
    	{
    		dp[1][sx][sy][0]=0;
    	}
    	for(int i=1;i<=t;i++){
    		for(int j=1;j<=h;j++){
    			for(int k=1;k<=w;k++){
    				for(int now=0;now<(1<<m);now++){
    					if(dp[i][j][k][now]==4557430888798830399){
    						continue;
    					}
    					if(can[i+1][j-1][k]){
    						if(flag[i+1][j-1][k]){
    							dp[i+1][j-1][k][now|(1<<(flag[i+1][j-1][k]-1))]=min(dp[i+1][j-1][k][now|(1<<(flag[i+1][j-1][k]-1))],dp[i][j][k][now]+1);
    						}else{
    							dp[i+1][j-1][k][now]=min(dp[i+1][j-1][k][now],dp[i][j][k][now]+1);
    						}
    					}
    					if(can[i+1][j][k-1]){
    						if(flag[i+1][j][k-1]){
    							dp[i+1][j][k-1][now|(1<<(flag[i+1][j][k-1]-1))]=min(dp[i+1][j][k-1][now|(1<<(flag[i+1][j][k-1]-1))],dp[i][j][k][now]+1);
    						}else{
    							dp[i+1][j][k-1][now]=min(dp[i+1][j][k-1][now],dp[i][j][k][now]+1);
    						}
    					}
    					if(can[i+1][j+1][k]){
    						if(flag[i+1][j+1][k]){
    							dp[i+1][j+1][k][now|(1<<(flag[i+1][j+1][k]-1))]=min(dp[i+1][j+1][k][now|(1<<(flag[i+1][j+1][k]-1))],dp[i][j][k][now]+1);
    						}else{
    							dp[i+1][j+1][k][now]=min(dp[i+1][j+1][k][now],dp[i][j][k][now]+1);
    						}
    					}
    					if(can[i+1][j][k+1]){
    						if(flag[i+1][j][k+1]){
    							dp[i+1][j][k+1][now|(1<<(flag[i+1][j][k+1]-1))]=min(dp[i+1][j][k+1][now|(1<<(flag[i+1][j][k+1]-1))],dp[i][j][k][now]+1);
    						}else{
    							dp[i+1][j][k+1][now]=min(dp[i+1][j][k+1][now],dp[i][j][k][now]+1);
    						}
    					}
    					if(can[i+1][j][k]){
    						if(flag[i+1][j][k]){
    							dp[i+1][j][k][now|(1<<(flag[i+1][j][k]-1))]=min(dp[i+1][j][k][now|(1<<(flag[i+1][j][k]-1))],dp[i][j][k][now]);
    						}else{
    							dp[i+1][j][k][now]=min(dp[i+1][j][k][now],dp[i][j][k][now]);
    						}
    					}
    				}
    			}
    		}
    	}
    	long long fk=0,ans=999999999;
    	for(int i=1;i<=h;i++){
    		for(int j=1;j<=w;j++){
    			if(dp[t][i][j][(1<<m)-1]==4557430888798830399){
    				continue;
    			}
    			ans=min(ans,dp[t][i][j][(1<<m)-1]);
    			fk=1;
    		}
    	}
    	if(fk==0){
    		cout<<-1<<endl;
    	}else{
    		cout<<ans<<endl;
    	}
    	return 0;
    }
    

    (谢谢观看!)

  • 相关阅读:
    Day13
    Day12
    Day11
    Day10
    Day9
    Day8
    Day7
    mac上使用gitlab拉项目报错Permissions 0644 for ...
    vue-cli3使用svg
    js合并多个array
  • 原文地址:https://www.cnblogs.com/lichangjian/p/15123810.html
Copyright © 2011-2022 走看看