A.HDU1024 Max Sum Plus Plus
题意
给你N个数,然后你分成M个不重叠部分,并且这M个不重叠部分的和最大.
思路
动态规划最大m字段和,dp数组,dp[i][j]表示以a[j]结尾的,i个字段的最大和
两种情况:1.第a[j]元素单独作为第i个字段
2.第a[j]元素和前面的字段共同当做第i个字段
得到状态转移方程:dp[i][j]=max( dp[i][j-1]+a[j] , max(dp[i-1][t])+a[j]);
但是实际情况是,时间复杂度和空间复杂度都是相当的高,所以要进行时间和空间的优化:
将每次遍历的时候的max(dp[i-1][t]) 用一个数组d储存起来,这样就能省去寻找max(dp[i-1][t])的时间,
这样状态转移方程就变成了 dp[i][j]=max( dp[i][j-1]+a[j] , d[j-1]+a[j]), 会发现dp数组的可以
省去一维,因为每次都是和前一次的状态有关,所以可以记录前一次状态,再用一个变量tmp记录下dp[i][j-1],
这样方程就变成了 dp[j]=max( num+a[j] , d[j-1]+a[j]);这样就可以化简一下就是:
dp[j]= max( num , d[j-1])+a[j];
在之后还要保存前面m-1的情况的最大状态,d[j-1]=ma;等于只有M-1组而且到这个位置时候的值,注意不能最大,因为最大虽然值大但是不保证是M-1个
1 |
|
B.HDU1029 Ignatius and the Princess IV
题意
给你n个数字,你需要找出出现至少(n+1)/2次的数字 现在需要你找出这个数字是多少?
方法一
直接用map记录次数然后扫一遍1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
using namespace std;
typedef long long ll;
const ll mod=998244353;
const int maxn=1e6+50;
const ll inf=0x3f3f3f3f3f3f3f3fLL;
map<int,int>mp;
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int n;
while(cin>>n){
int a;
mp.clear();
for(int i=0;i<n;i++){
cin>>a;
mp[a]++;
}
map<int,int>::iterator it;
int maid,ma=0;
for(it=mp.begin();it!=mp.end();it++){
if(it->second>=(n+1)/2){
maid=it->first;
}
}
cout<<maid<<endl;
}
return 0;
}
方法二
摩尔投票法
1 |
|
方法三
排序后输出中间位置的数
1 |
|
C.HDU1069 Monkey and Banana
题意
三维的最长带全严格上升子序列N个无限个数的三维方体,三维方体可以任意旋转(长宽高可以替换),现在让你求出这些正方体可以搭的最高高度,要求上面的矩形的长和宽必须严格小于下面的矩形的长宽,类似与三维的最长带全严格上升子序列
思路
一对长宽高可以构造出六种不同的正方体(长:三个取一个,宽:两个取一个,高:被固定了);然后根据长来排序,长相同根据宽排序,高不影响不管,依次判断最小面的是哪一个矩形,然后DP出这个矩形在下面时上面放那个矩形的最大值,最后求出一个最大值就行
1 |
|
D.HDU1074 Doing Homework
题意
有n个任务,每个任务有一个截止时间,超过截止时间一天,要扣一个分。
求如何安排任务,使得扣的分数最少,多种可能输出字典序最小的
思路
状压DP! 观察到N最大只有15,跟南京网络赛的E一样思路,想到了暴力枚举每个状态;然后枚举每一个在这状态完成的任务,假设他没完成让他在只有这个任务没完成的情况下完成的情况,因为题目要求是字典序小的先输出,所以同样的情况先枚举字典序大的,如果枚举完大的后,发现小的更好,那就可以直接替换了
1 |
|
E.HDU1087 Super Jumping! Jumping! Jumping!
题意
求最大递增子序列的权值和
1 |
|
F.HDU1114 Piggy-Bank
题意
有一个存钱罐,给出它的重量和装满硬币的重量,然后给出里面装的硬币的种类数,并给出每种硬币的面值和重量,求在给定重量的条件下硬币的最小价值
思路
根据重量从0开始推到给定的重量,每个从这个重量之前的重量找一个硬币的差距,然后选出一个最小值;默认为inf
完全背包:必须装满给出的重量,因此要使dp[0]=0,同时因为求的是最小值,因此其他位置应该是正无穷。
1 |
|
G.HDU1176 免费馅饼
题意
中文题
思路
二维DP,反向DP,
1 |
|
H.HDU1260 Tickets
题意
现在有n个人要买电影票,如果知道每个人单独买票花费的时间,还有和前一个人一起买花费的时间,问最少花多长时间可以全部买完票。
思路
关注最后一个买票的人,如果他自己买,那就是选择前面那个人的(和前面的前面那个买还是自己买的)的最小值;如果他和前面的买,那就减去前面自己买的钱,加上一起买的钱,最后选出最小值即可,这里因为考虑的只关于前一个人所以可以开一个二维滚动数组;
1 |
|
I.HDU1257 最少拦截系统
思路
本质上是求最长严格上升子序列,模拟成题意,就是
1.第一颗炮弹塞进数组中 拦截系统+1;
2.第二个炮弹大于第一颗炮弹,那就只能拦截系统+1;但是这个炮弹还能打比它小的导弹所以塞进数组中
3.如果第三个炮弹小于等于前面已经射出去的最高的炮弹,那就说明它可以被前面用过的炮弹打中,但是最优的策略是在前面用过的炮弹中选出一个大于它最小的炮弹用来替换,说明这个炮弹现在的位置在这了,如果等于最好,(但是有点题目是不能等于,比如最大不严格上升子序列,那就只能用upper_bound)
1 |
|
J.HDU1160 FatMouse’s Speed
题意
找到一个最多的老鼠序列,使得序列中的老鼠的体重满足递增,相应老鼠的速度满足递减。
思路
先按体重递增进行sort排序,然后按照体重找到最长递减子序列即可,用动态规划做比较简单。状态f[i]表示前i个老鼠中的最长递减子序列长度,状态转移方程为f[i] = max{f[j], mice[j].speed > mice[i].speed} + 1, 最后找出最大的f[i]即可。注意此题还需要输出找到的序列中的老鼠的最原始的标号,因此不仅要在刚开始的时候把每个老鼠的最初的序号记下来,还要在进行状态转移的时候把当前的老鼠的位置标记下来。
1 |
|
K.POJ1015 Jury Compromise
题意
1 | 在遥远的国家佛罗布尼亚,嫌犯是否有罪,须由陪审团决定。陪审团是由法官从公众中挑选的。先随机挑选n 个人作为陪审团的候选人,然后再从这n 个人中选m 人组成陪审团。选m 人的办法是:控方和辩方会根据对候选人的喜欢程度,给所有候选人打分,分值从0 到20。为了公平起见,法官选出陪审团的原则是:选出的m 个人,必须满足辩方总分D和控方总分P的差的绝对值|D-P|最小。如果有多种选择方案的|D-P| 值相同,那么选辩控双方总分之和D+P最大的方案即可。 |
1 |
|
L.POJ1458 Common Subsequence
题意
最长公共子序列
思路
1 |
|
M.POJ1661 Help Jimmy
题意
1 | 中文题,小人从最高点跳下 |
思路
1 | 1.可以从下枚举上去到起点 |
1 | //#include<bits/stdc++.h> |
N.POJ2533 Longest Ordered Subsequence
题意
最长递增子序列
1 |
|
O.POJ3186 Treats for the Cows
题意
给出n个数字v(i),每次你可以取出最左边的数字或者取出最右边的数字,一共取n次取完。假设你第i次取的数字是x,那么你可以获得i*x的价值。现在你需要规划取数顺序,使得总价值和最大。
思路
区间DP,方程
1 | //#include<bits/stdc++.h> |
P.HDU1078 FatMouse and Cheese
题意
1 | 有一种游戏是的玩法是这样的: |
思路
记忆化搜索,把每次搜索的结果存在DP里面 dp数组表示,这一个点接下去搜索能搜索到的最大值
1 |
|
Q.HDU2859 Phalanx
题意
给你一个矩阵,只由小写或大写字母构成。求出它的最大对称子矩阵的边长。
其中对称矩阵是一个kk的矩阵,它的元素关于从左下角到右上角的对角线对称。
例如下面这个3 3的矩阵是对称矩阵:
cbx
cpb
zcc
思路
dp ij 表示以点i,j为左下角的最大对称矩阵;发现以下规律
1.对于矩阵的最上面和最右边 i=1或者j=n的点为左下角的对称矩阵最大为1(就是它自己)
2.然后根据1可以得知,第二行最大的矩阵大小为2;并且最大的矩阵比第一个矩阵要多一个左边和右边的大小;
3.得出对于一个以该点为左下角的对称矩阵的最大大小由它的右上角的对称矩阵推出,而且最多比它大一圈;
1 |
|
R.POJ3616 Milking Time
题意
M个时间段,每个时间段有V价值,在每个时间段之间必须隔着R的时间,求最大价值和
思路
把时间段的起点排序一下,然后对于每个时间段判断前面的时间段间隔满不满足题意。然后选出价值最大的
1 | //#include<bits/stdc++.h> |
S.POJ3666 Making the Grade
题意
一个序列A,让你把它变成不严格递减或者不严格递增的序列B,花费是
思路
构造DP【i】【j】表示前面i个元素组成的不严格递减和不严格递增序列,其中J是这个序列中的最大值;
然后通过DP【i-1】求出最小值,中间利用了离散化
1 |
|