「NOIP模拟」蒜头君救人【动态规划】

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define ll long long
#define rep(i,x,y) for(ll i=(x);i<=(y);i++)
#define repl(i,x,y) for(ll i=(x);i<(y);i++)
#define repd(i,x,y) for(ll i=(x);i>=(y);i--)
using namespace std;

const ll Inf=1e18;

char ch[15][15];
ll n,m,t,st,tot,all,inf,v[15],pos[15],tt[2005];
ll mp[105][105],id[15][15],f[2005][2005][15];

ll dx[4]={0,0,1,-1},dy[4]={-1,1,0,0};

inline ll read() {
	ll x=0;char ch=getchar();bool f=0;
	while(ch>'9'||ch<'0'){if(ch=='-')f=1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
	return f?-x:x;
}

void File() {
	freopen("rescue.in","r",stdin);
	freopen("rescue.out","w",stdout);
}

int main() {
//	File();
	
	n=read(),m=read(),t=read();
	rep(i,1,n) scanf("%s",ch[i]+1);

	rep(i,1,n) rep(j,1,m) if('A'<=ch[i][j]&&ch[i][j]<='Z') v[0]++;
	
	char c[2];ll tmp;
	
	rep(i,1,v[0]) {
		scanf("%s%lld",c,&tmp);
		v[i]=tmp;
	}
	
	rep(i,1,n) rep(j,1,m) id[i][j]=++tot;

	rep(i,1,tot) rep(j,1,tot) mp[i][j]=Inf;

	rep(i,1,tot) mp[i][tot+1]=0;

	rep(i,1,n) rep(j,1,m) {
		if(ch[i][j]=='#') continue;
		
		ll x=i,y=j;
		
		rep(k,0,3) {
			ll tx=x+dx[k],ty=y+dy[k];
			
			if(tx&&ty&&tx<=n&&ty<=m&&ch[tx][ty]!='#') mp[id[x][y]][id[tx][ty]]=1;
		}
	}

    rep(k,1,tot) rep(i,1,tot) rep(j,1,tot) mp[i][j]=min(mp[i][j],mp[i][k]+mp[k][j]);

	rep(i,1,n) rep(j,1,m) {
		if(ch[i][j]=='s') st=id[i][j];

		if(ch[i][j]=='t') pos[v[0]+1]=id[i][j];

		if('A'<=ch[i][j]&&ch[i][j]<='Z') pos[ch[i][j]-'A'+1]=id[i][j];
	}
	
	all=(1<<v[0])-1;tt[0]=t;

    rep(i,1,all) {
    	ll sum=0;
    	rep(j,1,v[0]) if(i&(1<<(j-1))) sum+=v[j];
    	tt[i]=sum+t<1?1:sum+t;
	}

	memset(f,60,sizeof(f));
	
	rep(i,1,v[0]) 
	f[1<<(i-1)][0][i]=mp[st][pos[i]]*t;
	f[0][0][v[0]+1]=mp[st][pos[v[0]+1]]*t;

	inf=f[0][0][0];
	
	repl(j,0,all) rep(i,0,all) {
		if(i&j) continue;
		
		rep(x,1,v[0]+1) {
			if(f[i][j][x]==inf||(x<=v[0]&&(!((i>>x-1)&1)))) continue;
			
			rep(y,1,v[0]) {
				if((i>>y-1)&1||(j>>y-1)&1) continue;
				
				if(f[i|(1<<y-1)][j][y]>f[i][j][x]+tt[i]*mp[pos[x]][pos[y]]) f[i|(1<<y-1)][j][y]=f[i][j][x]+tt[i]*mp[pos[x]][pos[y]];
			}
			
			ll y=v[0]+1;
			if(f[i][j][y]>f[i][j][x]+tt[i]*mp[pos[x]][pos[y]]) f[i][j][y]=f[i][j][x]+tt[i]*mp[pos[x]][pos[y]];
		}
		
		for(ll s=i;s;s=s-1&i) f[i^s][j|s][v[0]+1]=min(f[i^s][j|s][v[0]+1],f[i][j][v[0]+1]);
	}

    printf("%lld",f[0][all][v[0]+1]);
	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/yanzhenhuai/article/details/83474582