洛谷P1373 小a和uim之大逃离
题目分析:
一道经典的dp题。这里的关键在于对于一种状态我们只关心两个人之间魔液之间的差值,而对他们手里具体有多少并不关心,从而大大减小时间和空间复杂度。从而dp的四个纬度分别是坐标i,j和差值以及最后拿的那个人是谁(这里也可以根据题目特性一次走两步再减少一个纬度,但因为实际上并没有优化效果故不采用)。其他还有一些需要注意的细节:①每次坐对于差值纬度都要%(k+1) ②这道题可能卡空间,大小要开得刚刚好并且不能用long long,只有最后记录结果的变量才需要long long
AC代码
#include <iostream>
#include <algorithm>
#include <iomanip>
#include <cmath>
#include <cstdio>
#include <vector>
#include <cstring>
#include <queue>
#include <map>
#include <stack>
#include <fstream>
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;
int dp[805][805][20][2];
int mp[805][805];
int n,m,k;
int main()
{
cin >> n >> m >> k;
k++;
memset(dp, 0, sizeof(dp));
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
{
scanf("%d",&mp[i][j]);
dp[i][j][mp[i][j]%k][0]=1;
}
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
for (int p=0;p<k;p++)
{
dp[i][j][p][0]=(dp[i][j][p][0]+dp[i-1][j][(p-mp[i][j]+k)%k][1])%1000000007;
dp[i][j][p][0]=(dp[i][j][p][0]+dp[i][j-1][(p-mp[i][j]+k)%k][1])%1000000007;
dp[i][j][p][1]=(dp[i][j][p][1]+dp[i-1][j][(p+mp[i][j])%k][0])%1000000007;
dp[i][j][p][1]=(dp[i][j][p][1]+dp[i][j-1][(p+mp[i][j])%k][0])%1000000007;
}
ll ans=0;
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
ans=(ans+dp[i][j][0][1])%1000000007;
cout << ans << endl;
}
洛谷P1156 垃圾陷阱
题目分析:
一道比较基础的dp题,类似于01背包问题。这里可以将井的深度看作背包容量,把拥有的能量看成是价值。那么我们就能用一个一维数组来表示在某一高度上能拥有的最大能量是多少。预处理时事先按时间进行排序,每投入一个物品就进行判断能量能否支撑到该物品投入,以及投入后若用来垫脚能否到达出口。以此每次更新相应高度上最大能量最终得到结果
AC代码:
#include <iostream>
#include <algorithm>
#include <iomanip>
#include <cmath>
#include <cstdio>
#include <vector>
#include <cstring>
#include <queue>
#include <map>
#include <stack>
#include <fstream>
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;
int dp[1000];
struct goods
{
int t;
int f;
int h;
};
int d,g;
goods a[1000];
bool cmp(goods x,goods y)
{
return x.t<y.t;
}
int main()
{
cin >> d >> g;
for (int i=1;i<=g;i++)
cin >> a[i].t >> a[i].f >> a[i].h;
sort(a+1, a+g+1, cmp);
memset(dp, 0, sizeof(dp));
dp[0]=10;
for (int i=1;i<=g;i++)
for (int j=d;j>=0;j--)
{
if (dp[j]>=a[i].t)
{
if (j+a[i].h>=d)
{
cout << a[i].t << endl;
return 0;
}
dp[j+a[i].h]=max(dp[j+a[i].h],dp[j]);
dp[j]+=a[i].f;
}
}
cout << dp[0] << endl;
}