Project Euler Problem 81-90
Project Euler 81-90题解
Problem 81 Path sum: two ways
路径和:两个方向
在如下的5乘5矩阵中,从左上方到右下方始终只向右或向下移动的最小路径和为2427,由标注红色的路径给出。
131 673 234 103 18
201 96 342 965 150
630 803 746 422 111
537 699 497 121 956
805 732 524 37 331
在这个31K的文本文件matrix.txt(右击并选择“目标另存为……”)中包含了一个80乘80的矩阵,求出从该矩阵的左上方到右下方始终只向右和向下移动的最小路径和。
简单的动态规划
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <vector>
using namespace std;
typedef long long LL;
typedef long double LD;
const int MAXN=102;
const int INF= 1e9;
int m,n,T;
int data[MAXN][MAXN],dp[MAXN][MAXN],dpp[MAXN][MAXN];
int getN()
{
char tmp;
int n=0;
do
{
tmp=getchar();
if(tmp>='0'&&tmp<='9')
n=n*10+int(tmp-'0');
}while(tmp>='0'&&tmp<='9');
//cout<<n<<" ";
return n;
}
int main()
{
freopen("p81in.txt","r",stdin);
m=n=80;
for(int i=0; i<m; i++)
for(int j=0; j<n; j++)
{
//scanf("%d",&data[i][j]);
data[i][j]=getN();
dp[i][j]=INF;
}
dp[0][0]=dpp[0][0]=data[0][0]; //init
for(int i=1; i<m; i++) //init
dp[i][0]=dpp[i][0]=dp[i-1][0]+data[i][0]; //init
for(int j=1; j<n; j++)
{
for(int i=0; i<m; i++) //right
dp[i][j]=dpp[i][j]=min(dp[i][j-1]+data[i][j],dp[i][j]);
for(int i=1; i<m; i++) //down
dp[i][j]=min(dp[i][j],dp[i-1][j]+data[i][j]);
//for(int i=m-2; i>=0; i--) //up
// dpp[i][j]=min(dpp[i][j],dpp[i+1][j]+data[i][j]);
for(int i=0; i<m; i++) //comebine
dp[i][j]=dpp[i][j]=min(dp[i][j],dpp[i][j]);
}
printf("Answer: %d",dp[n-1][n-1]);
return 0;
}
/**
131 673 234 103 18
201 96 342 965 150
630 803 746 422 111
537 699 497 121 965
805 732 524 37 331
**/
Problem 82 Path sum: three ways
路径和:三个方向
注意:这是第81题的一个更具挑战性的版本。
在如下的5乘5矩阵中,从最左栏任意一格出发,始终只向右、向上或向下移动,到最右栏任意一格结束的最小路径和为994,由标注红色的路径给出。
131 673 234 103 18
201 96 342 965 150
630 803 746 422 111
537 699 497 121 956
805 732 524 37 331
在这个31K的文本文件matrix.txt(右击并选择“目标另存为……”)中包含了一个80乘80的矩阵,求出从最左栏到最右栏的最小路径和。
动态规划
#include <algorithm>
#include <cstdio>
const int MAXN=102;
const int INF= 1e9;
int m,n,ans;
int data[MAXN][MAXN],dp[MAXN][MAXN],dpp[MAXN][MAXN];
int getN()
{
char tmp;
int n=0;
do
{
tmp=getchar();
if(tmp>='0'&&tmp<='9')
n=n*10+int(tmp-'0');
}
while(tmp>='0'&&tmp<='9');
return n;
}
int main()
{
freopen("p82in.txt","r",stdin);
m=n=80;
ans=INF;
for(int i=0; i<m; i++)
for(int j=0; j<n; j++)
{
data[i][j]=getN();
dp[i][j]=INF;
}
for(int i=0; i<m; i++) //init
dp[i][0]=dpp[i][0]=data[i][0]; //init
for(int j=1; j<n; j++)
{
for(int i=0; i<m; i++) //right
dp[i][j]=dpp[i][j]=min(dp[i][j-1]+data[i][j],dp[i][j]);
for(int i=1; i<m; i++) //down
dp[i][j]=min(dp[i][j],dp[i-1][j]+data[i][j]);
for(int i=m-2; i>=0; i--) //up
dpp[i][j]=min(dpp[i][j],dpp[i+1][j]+data[i][j]);
for(int i=0; i<m; i++) //comebine
dp[i][j]=dpp[i][j]=min(dp[i][j],dpp[i][j]);
}
for(int i=0; i<m; i++)
if(ans>dp[i][n-1])
ans=dp[i][n-1];
printf("Answer: %d",ans);
return 0;
}
/**
131 673 234 103 18
201 96 342 965 150
630 803 746 422 111
537 699 497 121 965
805 732 524 37 331
**/
Problem 83 Path sum: four ways
路径和:四个方向
注意:这是第81题的一个极具挑战性的版本。
在如下的5乘5矩阵中,从左上角到右下角任意地向上、向下、向左或向右移动的最小路径和为2297,由标注红色的路径给出。
131 673 234 103 18
201 96 342 965 150
630 803 746 422 111
537 699 497 121 956
805 732 524 37 331
在这个31K的文本文件matrix.txt(右击并选择“目标另存为……”)中包含了一个80乘80的矩阵,求出从左上角到右下角任意地向上、向下、向左或向右移动的最小路径和。
直接Dijkstra
#include<iostream>
#include<stdio.h>
#include<queue>
using namespace std;
#define INF 1e9
int const limit=80;
int mat[limit][limit],cnt=0;
int dist[limit*limit+5];
bool done[limit*limit+5]= {
0};
struct Edge
{
int to,cost;
bool operator < (const Edge & e) const
{
return this->cost>e.cost;
}
Edge(int t=0,int c=INF):to(t),cost(c) {}
} edges[limit*limit][4];
int getN()
{
char tmp;
int n=0;
do
{
tmp=getchar();
if(tmp>='0'&&tmp<='9')
n=n*10+int(tmp-'0');
}
while(tmp>='0'&&tmp<='9');
return n;
}
void addEdge(int x,int y,int i,int j)
{
if(i>=limit||j>=limit||i<0||j<0) return ;
edges[x*limit+y][cnt++]=Edge(i*limit+j,mat[i][j]);
}
void read()
{
for(int i=0; i<limit; i++) /// read from txt
for(int j=0; j<limit; j++)
mat[i][j]=getN();
///build Graph
for(int i=0; i<limit; i++)
for(int j=0; j<limit; j++)
{
cnt=0;
addEdge(i,j,i,j+1);
addEdge(i,j,i,j-1);
addEdge(i,j,i-1,j);
addEdge(i,j,i+1,j);
}
}
void dijkstra(int s=0)
{
priority_queue<Edge> pque;
for(int i=0; i<limit*limit; i++) dist[i]=INF;
dist[s]=mat[0][0];
pque.push(Edge(s,mat[0][0]));
while(!pque.empty())
{
Edge x=pque.top();pque.pop();
int u=x.to;
if(done[u]) continue;
done[u]=true;
for(int i=0; i<4; i++)
{
Edge & e=edges[u][i];
if(dist[e.to]>dist[u]+e.cost)
{
dist[e.to]=dist[u]+e.cost;
pque.push(Edge(e.to,dist[e.to]));
}
}
}
cout<<dist[limit*limit-1]<<endl;
}
int main()
{
freopen("p83in.t