UESTC 1134 男神的约会 状压DP

男神的约会

Time Limit: 3000/1000MS (Java/Others) 

 Memory Limit: 65535/65535KB (Java/Others)




有一天男神约了学姐姐去看电影,电影院有一个活动,给你一个10*10的矩阵,每一个格子上都有一个0-9的整数,表示一共十种优惠券中的一种。

观众从左上角的格子开始走,走到右下角。每走到一个有着a号优惠券的格子,都必须要玩一个a分钟的游戏来领取这张优惠券。每次只能向右或向

下走。当走到右下角的时候,如果集齐10种优惠券就可以半价看电影呢。为了能在学姐姐面前展示自己的才智,男神准备用最少的时间领取全部的

优惠券(他要省出最多的时间陪学姐姐)。聪明的你能告诉男神,他最少要花费的时间是多少?

Input

输入包含10行,每行10个数字,以空格隔开,表示格子上的优惠券的种类。数据保证存在合法路径。

Output

输出男神走到右下角的最小时间花费。


因为要收集10种道具,所以用二进制表示是否已经收集该道具 最多10位1111111111 所以每一个坐标需要1023个空间来储存每一种状态的耗费时间。
用dp[i][j][k]表示当位于(i,j)时,收集情况为[k]这种情况所耗费的时间,因为只能向右或者向左走,所以只需将上面和左边的各1024个情况扫一遍,然后找出

存在的情况转移一下。
用t表示这一格的道具,那么这一格的状态用左边或者上面的格子或运算一下就可以了。

转移方程:  dp[i][j][k|(1<<t)]=min(dp[i-1][j][k]+t,dp[i][j-1][k]+t)

最后再把dp[10][10][1023]输出来就可以了.

代码 :
//************************************************************************//
//*Author : Handsome How                                                 *//
//************************************************************************//
//#pragma comment(linker, "/STA	CK:1024000000,1024000000")
#pragma warning(disable:4996)
#include <vector>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <algorithm>
#include <sstream>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <cassert>
#if defined(_MSC_VER) || __cplusplus > 199711L
#define aut(r,v) auto r = (v)
#else
#define aut(r,v) __typeof(v) r = (v)
#endif
#define each(it,o) for(aut(it, (o).begin()); it != (o).end(); ++ it)
#define fur(i,a,b) for(int i=(a);i<=(b);i++)
#define furr(i,a,b) for(int i=(a);i>=(b);i--)
#define cl(a) memset((a),0,sizeof(a))
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define sc(x) scanf("%d",&x)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair <int, int> pii;
const int inf=0x3f3f3f3f;
const double eps=1e-8;
const int mod=1000000007;
const double pi=acos(-1);
inline void gn(long long&x){
	int sg=1;char c;while(((c=getchar())<'0'||c>'9')&&c!='-');c=='-'?(sg=-1,x=0):(x=c-'0');
	while((c=getchar())>='0'&&c<='9')x=x*10+c-'0';x*=sg;
}
inline void gn(int&x){long long t;gn(t);x=t;}
inline void gn(unsigned long long&x){long long t;gn(t);x=t;}
inline void gn(double&x){double t;scanf("%lf",&t);x=t;}
inline void gn(long double&x){double t;scanf("%lf",&t);x=t;}
//----------------------------------------------------------
int dp[11][11][1024];
int  fig[11][11];

void solve(){
	fur(i,1,10)fur(j,1,10){
		int t = 1<<fig[i][j];
			fur(k,0,1023)if(dp[i-1][j][k]!=inf)
				if(dp[i-1][j][k]<1000)
				dp[i][j][k|t]=min(dp[i][j][k|t],dp[i-1][j][k]+fig[i][j]);
			fur(k,0,1023)
				if(dp[i][j-1][k]<1000)
				dp[i][j][k|t]=min(dp[i][j][k|t],dp[i][j-1][k]+fig[i][j]);
	}
}

void init(){
	memset(dp,0x3f,sizeof(dp));
	int t = 1<<fig[1][1];
	dp[1][1][1<<fig[1][1]] = fig[1][1];
}

int main()
{
	fur(i,1,10)fur(j,1,10)gn(fig[i][j]);
	init();
	solve();
	printf("%d\n",dp[10][10][1023]);
	return 0;
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值