动态规划问题最重要的就是找到状态转移方程,而找到状态转移方程之前,需要先定义好dp数组表示的含义
动态规划就是要多练题,多写代码找感觉
首先,创建出地图
#include <bits/stdc++.h>
using namespace std;
int N;
int map[1600][1600];
int main()
{
cin >> N;
for(int i=1;i<=N;i++) //两层来输入地图
{
for(int j=1;j<=N;j++)
{
char ch;cin>> ch;
if(ch=='R') //用int数据来表示字符,右是0,下是-1,
map[i][j]=0; //用int数组好处是边界的数据可以一起存进去,而不需要额外开一个int数组
else
map[i][j]=-1;
}
cin>>map[i][N+1]; //存入边界数据(花费)
}
for(int i=1;i<=N;i++) //还剩最后一排数据没有存入
cin>>map[N+1][i];
}
好了,现在地图已经创建OK,开始考虑问题的解决
很容易想到:我们需要知道每个位置的牛的开销,才能得出总共的开销。
当一个位置的方向改变,那么,只有在他左方,上方,以及左上方的牛的开销可能会改变
那么我们就可以使用dp[i] [j]来表示i行j列的牛的花销是多少,我们先初始化dp数组
在初始化数组的同时,你就很容易发现可以找到状态转移方程
dp[x][y]无非等于它下面的牛或者它右边的牛的花销
res函数就实现了状态转移(先看第二个函数,再看第一个)
int res(int x,int y) //res函数返回map[x][y]点的牛的花销
{
if(map[x][y]==0) //如果map[x][y]为0,即方向向右,
dp[x][y]=dp[x][y+1]; //那么它就等于它右边一头牛的花销
else
dp[x][y]=dp[x+1][y]; //否则就等于它下面一头牛的花销
return dp[x][y];
}
//res函数还能将dp数组不断赋值,起到了初始化的作用
void Initial()
{
for(int i=1;i<=N;i++) //最右边的是饲料,直接将饲料赋值
dp[i][N+1]=map[i][N+1];
for(int j=1;j<=N;j++) //最下边的是饲料,直接将饲料赋值
dp[N+1][j]=map[N+1][j];
for(int i=N;i>0;i--) //逆序遍历,因为最靠近饲料的越快得到它的花销
{ //这也保证了每个dp元素可以得到它右方以及下方以及初始化的元素
for(int j=N;j>0;j--)
sum+=res(i,j); //用sum来保存第一次的所有牛的花销总和
} //之后就可以通过sum的增删来得出其他结果
}
开始执行换方向操作(先看第二个函数,再看第一个)
void reback(int x,int y)
{
if(x-1&&map[x-1][y]==-1) //如果x-1在合法边界&&上面的牛是向下的
{ //那么它就会被影响
sum-=dp[x-1][y];
res(x-1,y); //修改上面这个位置的牛的花销
sum+=dp[x-1][y];
reback(x-1,y); //继续递归,看上面的是不是也一样会被影响(可能左,可能上)
}
if(y-1&&map[x][y-1]==0) //y-1在合法边界&&左边的牛向右
{ //之后同上
sum-=dp[x][y-1];
res(x,y-1);
sum+=dp[x][y-1];
reback(x,y-1);
}
}
void operate()
{
int x,y;
cin>> x>> y;
if(map[x][y]==0) //改变方向
map[x][y]=-1;
else
map[x][y]=0;
sum-=dp[x][y]; //减去这个位置牛的先前花销
sum+=res(x,y); //加上这位置牛的现在花销
reback(x,y); //这个位置牛的花销改变了,那么花销可能
cout<<sum<<endl; //在左,上直接等于它的牛的花销也要改变,所以进行reback函数
}
以上的操作就差不多就能解决这道题啦
以下是这道题的全部代码(这道题不会爆int)
(不要嘲笑我臃肿的代码呜呜呜)
#include <iostream>
using namespace std;
int N,Q;
int map[1600][1600];
int dp[1600][1600];//保存
int sum=0;//保存
int res(int x,int y)//花费
{
if(map[x][y]==0)
dp[x][y]=dp[x][y+1];
else
dp[x][y]=dp[x+1][y];
return dp[x][y];
}
void reback(int x,int y)//更新变化之前
{
if(x-1&&map[x-1][y]==-1)
{
sum-=dp[x-1][y];
res(x-1,y);
sum+=dp[x-1][y];
reback(x-1,y);
}
if(y-1&&map[x][y-1]==0)
{
sum-=dp[x][y-1];
res(x,y-1);
sum+=dp[x][y-1];
reback(x,y-1);
}
}
void Initial()
{
for(int i=1;i<=N;i++)
dp[i][N+1]=map[i][N+1];
for(int j=1;j<=N;j++)
dp[N+1][j]=map[N+1][j];
for(int i=N;i>0;i--)
{
for(int j=N;j>0;j--)
sum+=res(i,j);
}
}
void operate()
{
int x,y;
cin>> x>> y;
if(map[x][y]==0)
map[x][y]=-1;
else
map[x][y]=0;
sum-=dp[x][y];
sum+=res(x,y);
reback(x,y);
cout<<sum<<endl;
}
signed main()
{
cin >> N;
for(int i=1;i<=N;i++)
{
for(int j=1;j<=N;j++)
{
char ch;cin>> ch;
if(ch=='R')
map[i][j]=0;
else
map[i][j]=-1;
}
cin>>map[i][N+1];
}
for(int i=1;i<=N;i++)
cin>>map[N+1][i];
Initial();
cin>> Q;
cout<<sum<<endl;
while(Q--)
{
operate();
}
return 0;
}