HDU1087题目大意:
给你一串序列,要求求出一个序列,必须是上升的,但是中途可以跳着走,比如1,3,7,6,8,11,5,6,7
那么你可以走1,3,7,8,11,也可以走1,3,6,8,11,还可以走1,3,5,6,7……然后要求这个求出的序列要最大。
解题思路:
用dp是比较好的选择。找出状态转移方程即可。
/*
*状态转移:dp[i] = max(dp[j] + num[i]); (1 <= j < i <= n, num[j] < num[i])
*/
#include
using namespace std;
const int MAX = 1005;
int main(void)
{
int n;
int dp[MAX], num[MAX];
while(scanf("%d", &n), n)
{
for(int i = 1; i <= n; i++)
scanf("%d", &num[i]);
for(int i = 1; i <= n; i++)
{
dp[i] = num[i];
for(int j = 1; j < i; j++)
{
if(num[j] < num[i])
dp[i] = max(dp[j] + num[i], dp[i]);
}
}
int max = -1000000000;
for(int i = 1; i <= n; i++)
{
if(dp[i] > max)
max = dp[i];
}
printf("%d\n", max);
}
return 0;
}
HDU1160题目大意:
给你一串数据,每行数据两个数,第一个是老鼠的重量,第二个是老鼠的速度,然后要求求最长子序列满足,老鼠的重量递增,但是速度递减,中途可以跳过几个。
解题思路:
跟上面那道题目是一样的道理,只是这一道要求打印路径,路径,直接用栈打印就可以了
代码:
/*
*状态转移:dp[i] = max(dp[j]+1, dp[i])
*判断条件:(1 <= j < i <= n, fat[j].w > fat[i].w && fat[j].s < fat[i].s)
*/
#include
#include
#include
using namespace std;
const int MAX = 1005;
typedef struct fat
{
int w, s;
int index;
} F;
F fat[MAX];
bool cmp(F a, F b)
{
if(a.w != b.w)
return a.w < b.w;
else
return a.s > b.s;
}
int main(void)
{
int s, w;
int index = 0, dp[MAX], path[MAX];
while(scanf("%d %d", &w, &s) == 2)
{
fat[index].index = index, fat[index].w = w, fat[index].s = s;
index++;
}
memset(path, -1, sizeof(path));
sort(fat, fat + index, cmp);
for(int i = 0; i < index; i++)
{
dp[i] = 1;
for(int j = 0; j < i; j++)
{
if(fat[j].w < fat[i].w && fat[j].s > fat[i].s)
{
if(dp[j] + 1 > dp[i]) //wa了两次,少加了这个条件,太可惜了,注意打路径的,要小心
{
dp[i] = dp[j] + 1;
path[fat[i].index] = fat[j].index;
}
}
}
}
int max = -1000000000, maxIndex = 0;
for(int i = 0; i < index; i++)
{
if(dp[i] > max)
{
max = dp[i];
maxIndex = i;
}
}
//输出结果跟路径
if(!index)
{
printf("0\n");
exit(0);
}
stack pathS;
int temp = fat[maxIndex].index;
while(temp != -1)
{
pathS.push(temp);
temp = path[temp];
}
printf("%d\n", max);
while(!pathS.empty())
{
printf("%d\n", pathS.top() + 1);
pathS.pop();
}
return 0;
}