2015 UESTC Training for Dynamic Programming 男神的约会 BFS+状压DP
2016-03-05 10:53
387 查看
D - 男神的约会
Time Limit:1000MS Memory Limit:65535KB 64bit IO Format:%lld & %llu
Submit Status Practice UESTC
1134
Appoint description:
System Crawler (2016-03-02)
Description
有一天男神约了学姐姐去看电影,电影院有一个活动,给你一个10*10的矩阵,每一个格子上都有一个0-9的整数,表示一共十种优惠券中的一种。
观众从左上角的格子开始走,走到右下角。每走到一个有着a号优惠券的格子,都必须要玩一个a分钟的游戏来领取这张优惠券。
每次只能向右或向下走。当走到右下角的时候,如果集齐10种优惠券就可以半价看电影呢。
为了能在学姐姐面前展示自己的才智,男神准备用最少的时间领取全部的优惠券(他要省出最多的时间陪学姐姐)。聪明的你能告诉男神,他最少要花费的时间是多少?
Input
输入包含10行,每行10个数字,以空格隔开,表示格子上的优惠券的种类。数据保证存在合法路径。
Output
输出男神走到右下角的最小时间花费。
Sample Input
0 1 2 3 4 5 6 7 8 9
1 1 1 1 1 1 1 1 1 0
2 1 1 1 1 1 1 1 1 0
3 1 1 1 1 1 1 1 1 0
4 1 1 1 1 1 1 1 1 0
5 1 1 1 1 1 1 1 1 0
6 1 1 1 1 1 1 1 1 0
7 1 1 1 1 1 1 1 1 0
8 1 1 1 1 1 1 1 1 0
9 1 1 1 1 1 1 1 1 5
Sample Output
50
Hint
题意:从(0,0)到(9,9)要求只能想右或者向下并领取所有的优惠券(各种不同的数字代表不同的优惠券),求最少所用的时间。
思路:从最少的时间大概能想到有BFS,但是对于判断当前领取的优惠卷就百思不得其解了,最后看了一下别人的思路才略有思路,因为每次只能向下或者向右,所以当前状态(i,j)只与(i-1,j)和(i,j-1)有关,所以就可以得出状态转移方程:dp[i][j][k|(1<<g[i][j])] = min(dp[i-1][j][k],dp[i][j-1][k])+g[i][j];(i-1,j)和(i,j-1)保证在范围内。
代码:
Time Limit:1000MS Memory Limit:65535KB 64bit IO Format:%lld & %llu
Submit Status Practice UESTC
1134
Appoint description:
System Crawler (2016-03-02)
Description
有一天男神约了学姐姐去看电影,电影院有一个活动,给你一个10*10的矩阵,每一个格子上都有一个0-9的整数,表示一共十种优惠券中的一种。
观众从左上角的格子开始走,走到右下角。每走到一个有着a号优惠券的格子,都必须要玩一个a分钟的游戏来领取这张优惠券。
每次只能向右或向下走。当走到右下角的时候,如果集齐10种优惠券就可以半价看电影呢。
为了能在学姐姐面前展示自己的才智,男神准备用最少的时间领取全部的优惠券(他要省出最多的时间陪学姐姐)。聪明的你能告诉男神,他最少要花费的时间是多少?
Input
输入包含10行,每行10个数字,以空格隔开,表示格子上的优惠券的种类。数据保证存在合法路径。
Output
输出男神走到右下角的最小时间花费。
Sample Input
0 1 2 3 4 5 6 7 8 9
1 1 1 1 1 1 1 1 1 0
2 1 1 1 1 1 1 1 1 0
3 1 1 1 1 1 1 1 1 0
4 1 1 1 1 1 1 1 1 0
5 1 1 1 1 1 1 1 1 0
6 1 1 1 1 1 1 1 1 0
7 1 1 1 1 1 1 1 1 0
8 1 1 1 1 1 1 1 1 0
9 1 1 1 1 1 1 1 1 5
Sample Output
50
Hint
题意:从(0,0)到(9,9)要求只能想右或者向下并领取所有的优惠券(各种不同的数字代表不同的优惠券),求最少所用的时间。
思路:从最少的时间大概能想到有BFS,但是对于判断当前领取的优惠卷就百思不得其解了,最后看了一下别人的思路才略有思路,因为每次只能向下或者向右,所以当前状态(i,j)只与(i-1,j)和(i,j-1)有关,所以就可以得出状态转移方程:dp[i][j][k|(1<<g[i][j])] = min(dp[i-1][j][k],dp[i][j-1][k])+g[i][j];(i-1,j)和(i,j-1)保证在范围内。
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <string> #include <queue> #include <cmath> #define ll long long #define inf 0x3f3f3f3f using namespace std; int g[12][12],dp[12][12][1<<11]; //dp[i][j][k]表示从坐标(0,0)走到当前坐标(i,j)而且当前状态为k时所使用的最少时间 int dir[2][2] = {{1,0},{0,1}};//两个方向(右或下) bool vis[12][12][1<<11];//标记每个点是否走过 struct Point { int x,y,k; Point(int _x = 0,int _y = 0,int _k = 0):x(_x),y(_y),k(_k){}; }; void BFS() { memset(vis,false,sizeof(vis)); memset(dp,inf,sizeof(dp)); Point head,next; queue<Point>q; Point p(0,0,1<<g[0][0]); vis[p.x][p.y][p.k] = true; dp[p.x][p.y][p.k] = g[p.x][p.y]; q.push(p); while(!q.empty()) { head = q.front(); q.pop(); for(int i = 0; i<2; i++)//两个方向(右或下) { next.x = head.x + dir[i][0]; next.y = head.y + dir[i][1]; if(next.x >= 0 && next.x <10 && next.y >= 0 && next.y <10)//判断是否出界了 { next.k = head.k|(1<<g[next.x][next.y]);//每走一步就把当前优惠券号标记住 dp[next.x][next.y][next.k] = min(dp[next.x][next.y][next.k],dp[head.x][head.y][head.k]+g[next.x][next.y]); if(!vis[next.x][next.y][next.k])//判断当前坐标是否走过了 { q.push(next); vis[next.x][next.y][next.k] = true; } } } } } int main() { #ifdef CDZSC_June freopen("t.txt","r",stdin); #endif for(int i = 0; i<10; i++) { for(int j = 0; j<10; j++) { scanf("%d",&g[i][j]); } } BFS(); printf("%d\n",dp[9][9][(1<<10) - 1]);//(1<<10) - 1)代表的是全部的优惠卷都领取了 return 0; }
相关文章推荐
- 关于《UNIX环境高级编程(第三版)》中apue.h头文件的设置
- API Guides(七)—— Property Animation To Media Playback
- HDU 5063 Operation the Sequence(暴力)
- According to TLD or attribute directive in tag file, attribute value does not accept any expressions
- 解决UITableView最后几个Item显示不全
- 修改UISearchBar 背景
- UIVIew相关知识
- uitextview 相关知识
- uicollectionview cell 行间距、列间距
- UIViewController相关知识
- UITableView相关知识
- UIlabel相关知识
- UITableViewCell头文件学习
- UIWindow
- UINavigationController
- UIButton常用属性
- UIKit性能调优实战讲解
- bzoj 1670: [Usaco2006 Oct]Building the Moat护城河的挖掘
- 62. Unique Paths
- 60. Permutation Sequence