1043 方格取数
2000年NOIP全国联赛提高组
设有N*N的方格图(N<=10,我们将其中的某些方格中填入正整数,而其他的方格中则放入数字0。如下图所示(见样例):
某人从图的左上角的A 点出发,可以向下行走,也可以向右走,直到到达右下角的B点。在走过的路上,他可以取走方格中的数(取走后的方格中将变为数字0)。
此人从A点到B 点共走两次,试找出2条这样的路径,使得取得的数之和为最大。
![](http://codevs.cn/media/image/problem/1043.png)
输入的第一行为一个整数N(表示N*N的方格图),接下来的每行有三个整数,前两个表示位置,第三个数为该位置上所放的数。一行单独的0表示输入结束。
只需输出一个整数,表示2条路径上取得的最大的和。
8
2 3 13
2 6 6
3 5 7
4 4 14
5 2 21
5 6 4
6 3 15
7 2 14
0 0 0
67
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> #include<iostream> using namespace std; int a[11][11]; int n,x,y,z; int f[11][11][11][11]; int main() { scanf("%d",&n); do { scanf("%d%d%d",&x,&y,&z); a[x][y]=z; }while(x!=0&&y!=0&&z!=0); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) for(int k=1;k<=n;k++) for(int l=1;l<=n;l++) { int x1=0,x2=0,x3=0,x4=0; x1=f[i-1][j][k-1][l]; x2=f[i-1][j][k][l-1]; x3=f[i][j-1][k-1][l]; x4=f[i][j-1][k][l-1]; f[i][j][k][l]=max(max(x1,x2),max(x3,x4)); if((i==k)&&(j==l)) f[i][j][k][l]+=a[i][j]; else f[i][j][k][l]+=(a[i][j]+a[k][l]); } printf("%d",f[n][n][n][n]); return 0; }
Yours和zero在研究A*启发式算法.拿到一道经典的A*问题,但是他们不会做,请你帮他们.
问题描述
在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格,空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变。
输入初试状态,一行九个数字,空格用0表示
只有一行,该行只有一个数字,表示从初始状态到目标状态需要的最少移动次数(测试数据中无特殊无法到达目标状态数据)
283104765
4
详见试题
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> #include <cstdio> #include <cstring> using namespace std; int c[9]={1,1,2,6,24,120,720,5040,40320};//1,2,3~8的阶乘 int dict2[4]={0,0,1,-1}, dict1[4]={-1,1,0,0}; int www; int step[400000]; int steps; char q[400000][9]; char mb[9]={1,2,3,8,0,4,7,6,5}; bool used[400000],sign; int hash(char str[9]) { int i,j,k; int f[10]; int sum=0; memset(f,0,sizeof(f)); for (i=0;i<9;i++) { k=0; for (j=0;j<8;j++) //找出第一个字符在字符串子串中是第几大。 if (j<str[i] && !f[j]) k++; f[str[i]]=1; //该字符已经判断过,以后的子串的第一个比较时不再和这个比较 sum+=k*c[8-i]; //存下an*(n-1)! } return sum; //总和 } void bfs() { int i,j,h,t; int x1,y1,z1,cx,cy,cz; memset(used,0,sizeof(used)); memset(step,0,sizeof(step)); www=hash(q[0]); used[www]=1; h=0; //队列头尾标记 t=1; while (h<t) { sign=0; for (i=0;i<9;i++) if (q[h][i]!=mb[i]) { sign=true; break; } if (!sign) { steps=step[h]; return; } for (i=0;i<9;i++) if (q[h][i]==0) { x1=i/3; y1=i%3; z1=i; break; } for (i=0;i<4;i++) { cx=x1+dict1[i]; cy=y1+dict2[i]; cz=cx*3+cy; if ((cx>=0) && (cx<3) && (cy>=0) && (cy<3)) { for (j=0;j<9;j++) q[t][j]=q[h][j]; q[t][z1]=q[h][cz]; q[t][cz]=0; www=hash(q[t]); if (!used[www]) { used[www]=1; step[t]=step[h]+1; t++; } } } h++; } steps=-1; return; } int main() { int i; char in[10]; scanf("%s",in); for (i=0;i<9;i++) q[0][i]=in[i]-'1'+1; bfs(); printf("%d",steps); return 0; }
在一个n*m的方阵中
寻找somebody的位置
有可能k不存在输出“biantai”
共n+1行
第一行 n m k
后n行为方阵
输出k的行和列
2 4 9
1 1 4 5
5 9 4 0
2 2
n<10 m<10
有可能k不存在输出“biantai”
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> #include<iostream> #include<cstring> using namespace std; int n,m,k; int a[11][11]; int x; int main() { scanf("%d%d%d",&n,&m,&k); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { scanf("%d",&x); if(x==k) { printf("%d %d",i,j); return 0; } } printf("biantai "); return 0; }