给一个n行n列的网格,每个格子里有一个1到9的数字。你需要从左上角走到右下角,其中每一步只能往上、下、左、右四个方向之一走到相邻格子,不能斜着走,也不能走出网格,但可以重复经过一个格子。为了美观,你经过的路径还必须关于“左下-右上”这条对角线对称。下图是一个6x6网格上的对称路径。
你的任务是统计所有合法路径中,数字之和最小的路径有多少条。
输入最多包含25组测试数据。每组数据第一行为一个整数n(2<=n<=100)。以下n行每行包含n个1到9的数字,表示输入网格。输入结束标志为n=0。
对于每组数据,输出合法路径中,数字之和最小的路径条数除以1,000,000,009的余数。
2 1 1 1 1 3 1 1 1 1 1 1 2 1 1 0
2 3
无
题意:这题有毒,题目条件给错的,n其实是200,并不是100,然后你开100的话会给你无限T, 哎,有毒的oj
其实就是在最短路上面多加一个状态即可。。。。。然后要注意,更新来的新点如果权值一样就不要加入到队列中,不然会超时
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#include<queue>
using namespace std;
typedef long long ll;
const ll mod = 1e9 + 9;
const int inf = 0x3f3f3f3f;
const int N = 222;
struct P
{
int x, y, sum;
ll cnt;
P(int x, int y, int sum, ll cnt) :x(x), y(y), sum(sum), cnt(cnt) {}
P() {}
bool operator < (const P& t1) const
{
return sum>t1.sum;
}
}dp[N][N];
int a[N][N], n, tmp;
int dx[] = { -1,0,1,0 };
int dy[] = { 0,1,0,-1 };
void bfs()
{
int i, j, sum;
priority_queue<P>que;
que.push(P(1,1,a[1][1]+a[n][n],1));
dp[1][1].sum = a[1][1] + a[n][n];
dp[1][1].cnt = 1;
while (!que.empty()) {
P now = que.top();
que.pop();
if(now.sum>dp[now.x][now.y].sum) continue;
if(now.sum>tmp) break;
if(now.x+now.y==n+1) {
tmp = min(tmp,dp[now.x][now.y].sum);
continue;
}
for (i = 0; i<4; i++) {
int tx = now.x + dx[i];
int ty = now.y + dy[i];
if (tx<1 || tx>n || ty<1 || ty>n) continue;
if (tx + ty == n + 1) sum = now.sum + a[tx][ty];
else sum = now.sum + a[tx][ty] + a[n + 1 - ty][n + 1 - tx];
if(dp[tx][ty].sum>sum) {
dp[tx][ty].sum = sum;
dp[tx][ty].cnt = dp[now.x][now.y].cnt;
que.push(P(tx,ty,sum,dp[tx][ty].cnt));
}
else if(dp[tx][ty].sum==sum) { // 这个点就不需要加入到队列中!!!!
dp[tx][ty].cnt += dp[now.x][now.y].cnt;
if(dp[tx][ty].cnt>mod) dp[tx][ty].cnt%=mod;
}
}
}
}
int main()
{
int i, j, x, y;
while (scanf("%d", &n) && n) {
for (i = 1; i <= n; i++)
for (j = 1; j <= n; j++)
{
scanf("%d", &a[i][j]);
dp[i][j].cnt = 0;
dp[i][j].sum = inf;
}
tmp = inf;
ll ans = 0;
bfs();
for (x = n; x>0; x--) {
y = n + 1 - x;
if (dp[x][y].sum<tmp) {
tmp = dp[x][y].sum;
ans = dp[x][y].cnt;
}
else if (dp[x][y].sum == tmp) {
ans = (ans + dp[x][y].cnt) % mod;
}
}
printf("%lld\n", ans%mod);
}
return 0;
}