hdu 3681 二分枚举答案+dp判断答案
来源:互联网 发布:淘宝最火的女装店铺 编辑:程序博客网 时间:2024/06/07 05:08
一开始以为是搜索,然后不知道怎么办了。。。那么多状态。。。因为那个夏天的风的分类是在搜索里面,最后看了解题报说是dp。。。。。
思路:
先用BFS搜出Y与G,G与F,F与Y的距离,然后就用二分枚举答案,用dp来判断答案是否能行。
dp就是一个TSP问题。。。。
我写的时候有一个地方要注意,就是dp判断里面结束的判断。。。一开始用的是〉~~的。。最后发现这样不行。。。。因为如果一个power位为1的话就能满足这个状态了。。。最后构造了一个变量judge来判断。。。
AC代码如下:
#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <cstdlib>#include <queue>using namespace std;typedef struct{int x, y;int step;}Point;int dp[16][1<<16];char maps[20][20];Point energy[16], switchs[16], point[20], start;int num_energy, num_switchs, num_sum;int N, M;int dis[20][20];int moves[][2] = { { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 } };int judge;int calc_dis( Point first, Point last ){queue<Point> q;bool mark[20][20];memset( mark, false, sizeof( mark ) );first.step = 0;q.push( first );mark[first.x][first.y] = true;while( !q.empty() ){Point n = q.front();q.pop();if( n.x == last.x && n.y == last.y ){return n.step;}for( int i = 0; i < 4; i++ ){Point temp;temp.x = n.x + moves[i][0];temp.y = n.y + moves[i][1];temp.step = n.step + 1;if( temp.x < 0 || temp.x >= N || temp.y < 0 || temp.y >= M || maps[temp.x][temp.y] == 'D' ){continue;}if( !mark[temp.x][temp.y] ){q.push( temp );mark[temp.x][temp.y] = true;}}}return -1;}bool check( int size ){memset( dp, -1, sizeof( dp ) );dp[0][1] = size;for( int i = 1; i <= ( 1 << ( num_sum + 1 ) ) - 1; i++ ){for( int j = 0; j <= num_sum; j++ ){if( dp[j][i] != -1 ){if( ( i & judge ) == judge ){//注意结束的判断,以及judge的构造return true;}for( int k = 1; k <= num_sum; k++ ){if( !( i & ( 1 << k ) ) && k != j ){if( k > num_switchs && dis[j][k] <= dp[j][i] && dis[j][k] != -1 ){dp[k][i|(1<<k)] = size;}else if( k <= num_switchs && dis[j][k] <= dp[j][i] && dis[j][k] != -1 ){if( dp[k][i|(1<<k)] == -1 ){dp[k][i|(1<<k)] = dp[j][i] - dis[j][k];}else{dp[k][i|(1<<k)] = max( dp[k][i|(1<<k)], dp[j][i] - dis[j][k] );}}}}}}}return false;}int main(){while( scanf( "%d%d", &N, &M ) && N && M ){memset( maps, 0, sizeof( maps ) );num_energy = 0;num_switchs = 0;for( int i = 0; i < N; i++ ){scanf( "%s", maps[i] );for( int j = 0; j < M; j++ ){if( maps[i][j] == 'F' ){start.x = i;start.y = j;}else if( maps[i][j] == 'Y' ){switchs[num_switchs].x = i;switchs[num_switchs++].y = j;}else if( maps[i][j] == 'G' ){energy[num_energy].x = i;energy[num_energy++].y = j;}}}num_sum = num_energy + num_switchs;for( int i = 1; i <= num_sum; i++ ){if( i <= num_switchs ){point[i] = switchs[i-1];}else{point[i] = energy[i-num_switchs-1];}}point[0] = start;judge = 0;//注意judge的构造for( int i = 0; i <= num_switchs; i++ ){judge |= ( 1 << i );}for( int i = 0; i <= num_sum; i++ ){for( int j = i + 1; j <= num_sum; j++ ){dis[i][j] = dis[j][i] = calc_dis( point[i], point[j] );}}int ans, l, r, mid;ans = 260;l = 0;r = ans;while( l <= r ){mid = ( l + r ) / 2;if( check( mid ) ){ans = min( mid, ans );r = mid - 1;}else{l = mid + 1;}}if( ans == 260 ){cout << -1 << endl;}else{cout << ans <<endl;}}return 0;}
0 0
- hdu 3681 二分枚举答案+dp判断答案
- 二分答案加DP判断
- HDU 3681 Prison Break (二分答案+状压DP+bfs预处理)
- hdu 4190 二分答案
- hdu 4190 #二分答案
- HDU-4190二分答案
- hdu 1105 二分答案
- HDU 2899 二分答案
- Live Archive2678 二分枚举答案
- poj 3658 二分枚举答案。
- hdoj 3586 Information Disturbing(二分答案+树dp判断)
- HDU 3861 Prison Breake 状态压缩dp+BFS+二分答案
- hdu 3433 A Task Process(二分答案+dp)
- [UOJ245]天路 枚举答案判断
- hdu3586(树形DP+二分答案)
- Topcoder SRM658,DP+二分答案,
- [dp][二分答案]最大正方形
- bzoj4985 评分(二分答案+dp)
- lua 学习笔记
- mysql5.5 启动报错:File './mysql-bin.index' not found (Errcode: 13)
- 哈弗曼树
- 黑马程序员------------------多态
- Java基础19--System--Runtime--Math--Date--Calendar
- hdu 3681 二分枚举答案+dp判断答案
- 最小堆
- ZOJ-2207
- 二叉查找树
- 设计模式之生成器模式
- Javascript实现打印局部网页功能
- 尺取法+LA2678
- 利用Javascript实时显示系统时间
- 二叉树