记忆化搜索
连续补了几天的DFS+BFS,整个人都不好了。。。
今天给大家简绍一些简单的东西——记忆化搜索,听起来虽然很高大上,但是的确挺好用,嘿嘿!!!(放心,这次没有那么难)怎么说呢,这个是真的不难,就是把算好的结果用一个数组存起来。直接上题吧!(不要问板子,这个内容已经水到没板子了)
传送门:Function Run Fun POJ - 1579
读完题直接写就ok了…先感受一下这个记忆化搜索…就是把算好的结果存起来…
#include<iostream>
#include<stdio.h>
#include<cstring>
using namespace std;
int dp[100][100][100];
int w(int a,int b,int c)
{
if(a<=0||b<=0||c<=0)
return 1;
if(a>20||b>20||c>20)
return w(20,20,20);
if(dp[a][b][c])
return dp[a][b][c];
if(a<b&&b<c)
return dp[a][b][c]=w(a,b,c-1)+w(a,b-1,c-1)-w(a,b-1,c);
else
return dp[a][b][c]=w(a-1,b,c)+w(a-1,b-1,c)+w(a-1,b,c-1)-w(a-1, b-1, c-1);
}
int main()
{
int a,b,c;
while(~scanf("%d %d %d",&a,&b,&c)&&a!=-1||b!=-1||c!=-1)
{
memset(dp,0,sizeof dp);
int tt=w(a,b,c);
printf("w(%d, %d, %d) = %d\n",a,b,c,tt);
}
return 0;
}
传送门:滑雪 POJ - 1088
熟悉的DFS,就是加了一个记忆化数组,水水水起来…
#include<iostream>
#include<stdio.h>
#include<cstring>
//#include<bits/stdc++.h>
using namespace std;
int dp[110][110];
int mp[110][110];
int n,m;
int dd[4][2]={-1,0,1,0,0,1,0,-1};
int dfs(int x,int y)
{
if(dp[x][y])
return dp[x][y];
int maxlen=1;
int len;
for(int i=0;i<4;i++)
{
int dx=x+dd[i][0];
int dy=y+dd[i][1];
if(dx>=0&&dy>=0&&dx<n&&dy<m&&mp[dx][dy]<mp[x][y])
{
len=dfs(dx,dy)+1;
maxlen=max(len,maxlen);
}
}
return dp[x][y]=maxlen;
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
memset(dp,0,sizeof dp);
memset(mp,0,sizeof mp);
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
cin>>mp[i][j];
int cnt=0;
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
int tt=dfs(i,j);
cnt=max(tt,cnt);
}
}
cout<<cnt<<endl;
}
return 0;
}
传送门: FatMouse and Cheese HDU - 1078
#include<iostream>
#include<stdio.h>
#include<cstring>
using namespace std;
int n,m,step;
int a[110][110];
int dp[110][110];
int dd[4][2]={-1,0,1,0,0,1,0,-1};
int dfs(int x,int y)
{
if(dp[x][y])
return dp[x][y];
int ans=0;
for(int i=0;i<4;i++)
{
for(int j=1;j<=m;j++)
{
int dx=x+dd[i][0]*j;
int dy=y+dd[i][1]*j;
if(dx>=0&&dy>=0&&dx<n&&dy<n&&a[dx][dy]>a[x][y])
{
int tmp=dfs(dx,dy);
if(ans<tmp)
ans=tmp;
}
}
}
dp[x][y]=ans+a[x][y];
return dp[x][y];
}
int main()
{
while(~scanf("%d%d",&n,&m)&&n!=-1||m!=-1)
{
memset(dp,0,sizeof dp);
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
cin>>a[i][j];
dfs(0,0);
cout<<dp[0][0]<<endl;
}
return 0;
}
传送门:Bone Collector HDU - 2602
这是个背包问题,先看看吧!以后会详细简绍背包问题。
#include<iostream>
#include<stdio.h>
#include<cstring>
using namespace std;
int w[1000]; //保存物品的重量
int v[1000]; //保存物品的价值
int dp[1000][1000]; //记忆化数组,要初始化为-1
int n,vv; //n个物品
// 从第i个物品开始挑选总重量小于j的部分
int dfs(int i,int j)
{
if(dp[i][j] >= 0)
return dp[i][j]; //已经计算过的话直接使用之前的结果
int res;
if(i == n)
res = 0; //已经没有物品
else if (j < w[i])
res = dfs(i + 1,j); //无法挑选
else
res = max(dfs(i + 1, j), dfs(i + 1,j - w[i]) + v[i]); //挑选和不挑选两种情况都尝试一下
return dp[i][j] = res; //保存结果并返回
}
int main()
{
int T;
cin>>T;
while(T--)
{
memset(dp,-1,sizeof dp);
cin>>n>>vv;
for(int i=0;i<n;i++)
cin>>v[i];
for(int j=0;j<n;j++)
cin>>w[j];
int ff=dfs(0,vv);
cout<<ff<<endl;
}
return 0;
}
传送门:漫步校园 HDU - 1428
给大家一个CV代码,这个我没做出来…
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n;
struct node
{
int x,y,c;
bool friend operator <(node a,node b)
{
return a.c>b.c;
}
}r,w;
ll ma[305][305],vis[305][305],dis[305][305],dp[305][305];
int d[4][2]={0,1,1,0,-1,0,0,-1};
void bfs()
{
priority_queue<node> q;
r.x=n-1,r.y=n-1;r.c=ma[n-1][n-1];
dis[n-1][n-1]=ma[n-1][n-1];
vis[n-1][n-1]=1;
q.push(r);
while(!q.empty())
{
r=q.top();
q.pop();
for(int i=0;i<4;i++)
{
int dx=r.x+d[i][0];
int dy=r.y+d[i][1];
if(dx<0||dy<0||dx>=n||dy>=n||vis[dx][dy])
continue;
w.x=dx,w.y=dy,w.c=r.c+ma[dx][dy];
vis[dx][dy]=1;
q.push(w);
dis[dx][dy]=w.c;
}
}
}
ll dfs(ll x,ll y)
{
if(x==n-1&&y==n-1) return 1;
if(dp[x][y]!=-1) return dp[x][y];
dp[x][y]=0;
for(int i=0;i<4;i++)
{
int dx=x+d[i][0];
int dy=y+d[i][1];
if(dx<0||dy<0||dx>=n||dy>=n||dis[dx][dy]>=dis[x][y]) continue;
dp[x][y]+=dfs(dx,dy);
}
return dp[x][y];
}
int main()
{
while(cin>>n)
{
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
cin>>ma[i][j];
memset(vis,0,sizeof(vis));
memset(dp,-1,sizeof(dp));
bfs();
cout<<dfs(0,0)<<endl;
}
}