ZOJ 2634 Collecting Stones
来源:互联网 发布:足球游戏源码 编辑:程序博客网 时间:2024/06/14 21:29
题意:给你8*8的矩阵,从(1,1)走到(8,8),每个点只能走一次,且只能走上下右,右上,右下这五个方向。问:是否能使权值和恰为m?
思路:dfs+剪枝,不错的剪枝搜索。
设当前走到(x,y),权值和为sum,g[x][y]表示(x,y)的权值。
1.后缀和剪枝。设第y列到第8列整个子矩阵和为sufSum,剪掉 sum+sufSum<m 的情况。
2.dp剪枝。设dp[x][y][d]表示在(x,y)从d方向出去到(8,8)的最小权值和,剪掉 sum+dp[x][y][d]-g[x][y]>m。设dp2[x][y][d]表示在(x,y)从d方向出去到(8,8)的最大权值和,剪掉sum+dp2[x][y][d]-g[x][y]<m。
3.sum剪枝。剪掉sum>m。
剪掉上面3条,基本可以AC了。
顺便附上#1 AC图,纪念下:
代码:
//#pragma comment(linker, "/STACK:134217728,134217728") /*128Mb*///#pragma comment(linker,"/STACK:33554432") /*32Mb*///#pragma comment(linker,"/STACK:16777216") /*16Mb*/#include <algorithm>#include <iostream>#include <string>#include <string.h>#include <stdio.h>#include <math.h>#include <stdlib.h>#include <vector>#include <queue>#include <stack>#include <cmath>#include <list>#include <set>#include <map>using namespace std;/*--in common define-----*/#define N 1000010#define E 100010#define ll long long#define INF 0xfffffffconst int PRIME =999983;const int MOD =1000000007;const int MULTI =1000000007;/*--end in common define-*//*--in common use--------*/#define CUBE(x) ((x)*(x)*(x))#define SQ(x) ((x)*(x))#define ALL(x) x.begin(),x.end()#define CLR(x,a) memset(x,a,sizeof(x))inline bool isodd(int x){return x&1;}inline bool isodd(ll x) {return x&1;}/*--end in common use----*/int n,g[10][10];int dp[10][10][6],dp2[10][10][6];int dx[5]={-1,1,0,-1,1};int dy[5]={0,0,1,1,1};int sufSum[10];bool visit[10][10],legal;void dfs(int x,int y,int sum){sum+=g[x][y];int xx,yy,Min=INF;if(sum>n) return ;if(x==8 && y==8){if(sum==n) legal=true;return ;}for(int i=0;i<5;i++){xx=dx[i]+x;yy=dy[i]+y;if(xx<1 || xx>8 || yy<1 || yy>8) continue;if(visit[xx][yy]) continue;if(sum+sufSum[y]<n) continue;if(sum+dp[x][y][i]-g[x][y]>n) continue;if(sum+dp2[x][y][i]-g[x][y]<n) continue;visit[xx][yy]=true;dfs(xx,yy,sum);if(legal) return ;visit[xx][yy]=false;}}int predfs(int x,int y,int prex,int prey){int xx,yy,Min=INF;if(x==8 && y==8){return g[8][8];}for(int i=0;i<5;i++){xx=dx[i]+x;yy=dy[i]+y;if(xx<1 || xx>8 || yy<1 || yy>8) continue;if(xx==prex && yy==prey) continue;if(dp[x][y][i]!=-1) Min=min(Min,dp[x][y][i]);else Min=min(Min,(dp[x][y][i]=predfs(xx,yy,x,y)+g[x][y]));}return Min;}int predfs2(int x,int y,int prex,int prey){int xx,yy,Max=-INF;if(x==8 && y==8){return g[8][8];}for(int i=0;i<5;i++){xx=dx[i]+x;yy=dy[i]+y;if(xx<1 || xx>8 || yy<1 || yy>8) continue;if(xx==prex && yy==prey) continue;if(dp2[x][y][i]!=-1) Max=max(Max,dp2[x][y][i]);else Max=max(Max,(dp2[x][y][i]=predfs2(xx,yy,x,y)+g[x][y]));}return Max;}void pretreat(){CLR(sufSum,0);CLR(visit,0);visit[1][1]=true;legal=false;for(int i=1;i<=8;i++)for(int j=1;j<=8;j++)sufSum[j]+=g[i][j];for(int i=7;i>=1;i--)sufSum[i]+=sufSum[i+1];for(int i=0;i<5;i++)dp[8][8][i]=dp2[8][8][i]=g[8][8];}int main(){int re;scanf("%d",&re);while(re--){scanf("%d",&n);for(int i=1;i<=8;i++)for(int j=1;j<=8;j++)scanf("%d",&g[i][j]);CLR(dp,-1);CLR(dp2,-1); predfs(1,1,0,0);predfs2(1,1,0,0);pretreat();dfs(1,1,0);if(legal) puts("Yes");else puts("No");}return 0;}
- Zoj 2634 Collecting Stones
- ZOJ 2634 Collecting Stones
- Stones
- Stones
- Stones
- Stones
- Stones
- ZOJ 3964 Yet Another Game of Stones (博弈)
- ZOJ 3964 Yet Another Game of Stones(博弈论)
- ZOJ 3964 Yet Another Game of Stones (博弈)
- ZOj 3964Yet Another Game of Stones(nim博弈)
- Yet Another Game of Stones---ZOJ Problem 3964
- ZOJ 3964 Yet Another Game of Stones(Nim博弈 待整理)
- Music Collecting
- URI collecting
- face collecting
- 3stones
- HDU1896- Stones
- 6个有用的MySQL语句
- AUTOSAR
- android调试工具集
- Attach函数的讲解
- ThinkPHP3.1快速入门(2)数据CURD
- ZOJ 2634 Collecting Stones
- 修改Android中strings.xml文件及转义字符
- 对封装的理解
- 后缀数组求rank数组,sa数组
- 关于Ext后台生成控件和得到控件值的方法总结
- PhoneGap实例
- ActiveX控件实现IobjectSafety接口
- Linux上Core Dump文件的形成和分析
- hdu 1251 统计难题(字典树模版)