1.并查集:数组并查,高效的判断数据是否在同一集合,套用代码模板即可。
递归调用find(x);循环归并Merge(a,b);fd[a]=b;
2.背包问题:分为0-1背包,完全背包,多重背包 问题。
使用动态规划,代码简介,功能强大,需要较多的时间去理解思考。也是计算机科学与程序设计神奇魅丽所在。
计算转移方程,推荐二维数组,理解方便。背包问题在二维数组中转换。
可以压缩成一维滚动数组,计算好利用的存储位置,进行压缩。
有N件物品装入容量为V的背包。第i件物品费用是w[i],价值是p[i],求解不超过背包容量的最大价值。
转移方程:f[i][v]=max{f[i-1][v],f[i-1][v-w[i]]+p[i]};
压缩一维:for(int i=1;i<=n;i++) for(int v=V;v>=w[i];--v) f[v]=max(f[v],f[v-w[i]]+p[i]); cout<<f[V]<<endl;
3.果园里有水果若干堆,现将所有水果合并成一堆。每一次合并,可以将两堆水果合并到一起,消耗的体力等于两堆水果重量之和。经过N-1次合并后,变成一堆。合并时消耗的体力等于每次合并消耗的体力之和。求设计出合适的合并次序方案,计算使得合并消耗体力之和最小。
假定每个水果重量均为1,如果有3堆水果,数目依次为1,2,9.可以先将1,2堆合并,耗费体力为3,再与第三堆合并,耗费体力为12,共耗费体力3-12-15.可以证明,15为最小体力耗费值。
水果堆数<=10000,每堆数目<=10000;
解法:贪心+最小堆
priority_quequ < int , vector <int>, greater <int> > q;
优先队列,最高优先级总是第一个出队列。greater:从小到大
4.动态规划=递归+中间计算保存 or 递推
吉哥一共有m天的假期,每天的编号从1到m,一共有n份可以做的工作,每份工作都知道起始时间s,终止时间e和对应的工资c,每份工作的起始和终止时间以天为单位(即天数编号),每份工作必须从起始时间做到终止时间才能得到总工资c,且不能存在时间重叠的工作。比如,第1天起始第2天结束的工作不能和第2天起始,第4天结束的工作一起被选定,因为第2天吉哥只能在一个地方工作。
现在,吉哥想知道怎么安排才能在假期的m天内获得最大的工资数(第m+1天吉哥必须返回学校,m天以后起始或终止的工作是不能完成的)。
Input:第一行是数据的组数T;每组数据的第一行是2个正整数:假期时间m和可做的工作数n;接下来n行分别有3个正整数描述对应的n个工作的起始时间s,终止时间e,总工资c。
动归:dp[i]表示到今天所能挣到的最多的钱,dp[i]= MAX(dp[i],dp[j]+a[j+1][i]);其中a[i][j]:从第i天到j天的工资。
int iHoliday,iWorks,iStart,iEnd,iSalary;
int iWorkDay[MAXN][MAXN];
int dp[MAXN];
for(int i=0;i<iWorks;++i)
{
scanf(&iStart,&iEnd,&iSalary);
if(iStart>iHoliday || iEnd > iHoliday) continue;
if(iSalary>iWorkDay[iStart][iEnd]) iWorkDay[iStart][iEnd] = iSalary;
}
for(int i=1;i<= iHoliday;++i)
{
for(int j=0;j<i;++j)
dp[i]=MAX(dp[i],dp[j]+iWorkDay[j+1][i]);
}
5.
工作室是一个N行M列的矩形布局,小Q暗自给每个同事进行了评分(为区别男女,男生一律用负整数,女生一律用正整数)。
现在,小Q把所有人的数据记录下来,并且这样定义一个位置的价值:
1、一个位置的价值只和其上下左右四个邻居的魅力值有关(对于靠边的位置,只考虑其存在的邻居);
2、如果某位置的邻居和该位置主人性别不同,则总分加上邻居魅力值的绝对值,否则减去;
3、对周围所有邻居的数据处理后,最终的得分即为这个位置的最终得分,得分越高,则该位置越好;
计算一下最佳位置?