UVA 607-Scheduling Lectures(贪心+DP)

题目大意:有n(n大于等于1小于等于1000)个主题,每个主题要花费t1,t2,……,tn(每个ti都不会大于L)的时间来讲,每个讲座L(L大于等于1小于等于500)分钟;安排讲座有两个规则:

不能讲一个主题分在两个讲座讲;

必须按顺序讲,即ti要在ti-1之后讲。

每个讲座都有一个DI值,(即不满意值)设t为提前下课的分钟数,则:

DI=0(若t=0)或DI=-C(若t大于等于1小于等于10)或DI=(t-10)的平方(若t大于10)。

求出最少安排多少个讲座能将所有主题讲完,并且求出在最少讲座的情况下不满意度的最小值是多少。

先用贪心,尽量把课往前安排,求出最少用多少次讲座可以讲完。记b[i]为前i个讲座最多包含的主题的数量(即前i个讲座最多包含b[i]个主题,再多就安排不下);再从后往前贪心,记c[i]为前i个讲座最少包含的主题的数量(即前i个讲座最少安排c[i]个主题,否则就不能产生最优解了)。之后动态规划。d[i][j]表示前i个讲座包含j个主题最小的不满意值,用e[i][j]表示主题i到j安排在一个讲座内,DI值是多少。

状态转移方程:d[i][j]=min { d[i-1][u]+e[u+1][j] }(j从c[i]变化到b[i],u从c[i-1]变化到b[i-1])

#include<stdio.h>
#include<stdlib.h>
int a[1100];
int b[1100];
int c[1100];
int d[1100][1100];
int sum[1100][1100];
int main(void)
{
	int i,j,n,m,p,q,u,v,min,co;
	co=0;
	scanf("%d",&n);
	while(n!=0)
	{
		co++;
		scanf("%d%d",&m,&p);
		for(i=1;i<=n;i++)
		{
			scanf("%d",&a[i]);
		}
		for(i=1;i<n;i++)
		{
			sum[i][i]=a[i];
			for(j=i+1;j<=n;j++)
			{
				sum[i][j]=sum[i][j-1]+a[j];
			}
		}
		sum[n][n]=a[n];
		u=0;
		v=1;
		for(i=1;i<=n;i++)
		{
			if(u+a[i]>m)
			{
				b[v]=i-1;
				i--;
				u=0;
				v++;
			}
			else
			{
				u=u+a[i];
			}
		}
		b[v]=n;
		c[v]=n;
		b[0]=v;
		u=0;
		v--;
		for(i=n;i>=1;i--)
		{
			if(u+a[i]>m)
			{
				c[v]=i;
				i++;
				u=0;
				v--;
			}
			else
			{
				u=u+a[i];
			}
		}
		for(u=c[1];u<=b[1];u++)
		{
			if(sum[1][u]==m)
			{
				d[1][u]=0;
			}
			else if(m-sum[1][u]>10)
			{
				d[1][u]=(m-sum[1][u]-10)*(m-sum[1][u]-10);
			}
			else
			{
				d[1][u]=-p;
			}
		}
		for(i=2;i<=b[0];i++)
		{
			for(u=c[i];u<=b[i];u++)
			{
				min=100000000;
				for(v=c[i-1];v<=b[i-1];v++)
				{
					if((v<=u)&&(sum[v+1][u]<=m))
					{
						if(sum[v+1][u]==m)
						{
							q=d[i-1][v];
						}
						else if(m-sum[v+1][u]>10)
						{
							q=d[i-1][v]+(m-sum[v+1][u]-10)*(m-sum[v+1][u]-10);
						}
						else
						{
							q=d[i-1][v]-p;
						}
						if(q<min)
						{
							min=q;
						}
					}
				}
				d[i][u]=min;
			}
		}
		printf("Case %d:\n",co);
		printf("Minimum number of lectures: %d\n",b[0]);
		printf("Total dissatisfaction index: %d\n",d[b[0]][n]);
		scanf("%d",&n);
		if(n!=0)
		{
			printf("\n");
		}
	}
	return 0;
}
时间: 2024-10-01 16:56:30

UVA 607-Scheduling Lectures(贪心+DP)的相关文章

递推DP UVA 607 Scheduling Lectures

题目传送门 题意:教授给学生上课,有n个主题,每个主题有ti时间,上课有两个限制:1. 每个主题只能在一节课内讲完,不能分开在多节课:2. 必须按主题顺序讲,不能打乱.一节课L时间,如果提前下课了,按照时间多少,学生会有不满意度.问最少要几节课讲完主题,如果多种方案输出不满意度最小的 分析:dp[i]表示前i个主题最少要多少节课讲完,那么这个主题可能和上个主题在同一节课讲或者多开新的一节课讲,状态转移方程:看代码:优先满足节数少的情况 收获:普通的递推DP 代码: /**************

uva607 - Scheduling Lectures(递推)

题目:uva607 - Scheduling Lectures(递推) 题目大意:有N个主题,每个主题都有个讲课的时间.然后给定每节课的时间,并且要求一门课只能被选一次,并且选两门课以上的要选连续的.这样子每节课都有个真实的上课时间.根据这个和预期的上课时间求每节课的badness.要求在课最少的情况下.badness的和最小. 解题思路:这题不难想到状态转移方程dp[i][j]前j个主题分成了i组得到的最小的badness. dp[i][j] = Min(dp[i - 1][k] + badn

UVA 10317 - Equating Equations 贪心 dfs

UVA 10317 - Equating Equations 贪心 dfs ACM 题目地址:UVA 10317 - Equating Equations 题意: 给一个等式,但是这个等式不一定是正确的,要你对等式中的数字重新排序,使得等式成立.等式只有+和-,数字个数小于16. 分析: 以a + b - c = d - e为例子. 1. 我们把等式右边的各项都换到左边,a + b - c - d + e = 0 2. 把+项和-项放一起,就变成(a + b + e) - (c + d) = 0

uva 12186 Another Crisis 树形dp

// uva 12186 Another Crisis 树形dp // // 对于一个节点u,有k个子节点,则至少有c = (k * T - 1) / 100 + 1才能 // 发信,即c / k >= T / 100,则 c 的值为 k * T /100,上取整变成上式 // 将所有的子节点d从小到大排序,取前c个就是d[u]的值 // 紫书上的一题,之前看了好久好久,觉得挺好的,然而一直没做,今天就来 // 体验体验,挺好的一题,注意一下,如果一个节点是叶节点,直接return 1就好 //

UVA 1399 - Puzzle(AC自动机+DP)

UVA 1399 - Puzzle 题目链接 题意:给定一些字符串,求一个最长的不在包含这些子串的字符串,如果可以无限长输出No 思路:建ACM自动机,把不可走结点标记构造出来,然后在这个状态图上进行dp找出最长路径即可,至于无限长的情况,只要在dp前进行一次dfs判有没有环即可 代码: #include <cstdio> #include <cstring> #include <string> #include <algorithm> #include &

URAL 1203 Scientific Conference(贪心 || DP)

Scientific Conference 之前一直在刷计算几何,邀请赛连计算几何的毛都买见着,暑假这一段时间就做多校,补多校的题目,刷一下一直薄弱的DP.多校如果有计算几何一定要干掉-.- 题意:给你N个报告会的开始时间跟结束时间,问你做多可以听几场报告会.要求报告会之间至少间隔为1. 思路:其实是个活动安排问题,可以用贪心也可以用DP,贪心写起来会比较简单一些,因为练习DP,所以又用DP写了一遍. 贪心的话就是一个很简单的活动选择问题,从结束时间入手,找每次的最优选择. 1 struct n

UVA 1558 - Number Game(博弈dp)

UVA 1558 - Number Game 题目链接 题意:20之内的数字,每次可以选一个数字,然后它的倍数,还有其他已选数的倍数组合的数都不能再选,谁先不能选数谁就输了,问赢的方法 思路:利用dp记忆化去求解,要输出方案就枚举第一步即可,状态转移过程中,选中一个数字,相应的变化写成一个函数,然后就是普通的博弈问题了,必胜态之后必有必败态,必败态之后全是必胜态 代码: #include <stdio.h> #include <string.h> const int N = 105

uva 417 - Word Index(数位dp)

题目连接:uva 417 - Word Index 题目大意:按照题目中的要求,为字符串编号,现在给出字符串,问说编号为多少,注意字符串必须为递增的,否则编号为0. 解题思路:其实就是算说比给定字符串小并且满足递增的串由多少个.dp[i][j]表示第i个位为j满足比给定字符串小并且满足递增的串. dp[i][j]=∑k=0j?1dp[i?1][k]. 注意每次要处理边界的情况,并且最后要加上自身串.并且在处理边界的时候dp[i][0]要被赋值为1,代表前i个为空的情况. #include <cs

UVA 10641 - Barisal Stadium(DP + 几何)

题目链接:10641 - Barisal Stadium 题意:逆时针给定n个点,在给m个灯,每个灯有一个花费,要求最小花费使得所有边能被灯照到 思路:用向量叉积判断向量的顺逆时针关系,从而预处理出每个灯能照到的边,然后由于n个点是环的,所以可以直接扩大两倍,dp时候去枚举起点即可 状态为dp[i]表示现在照到i条边之前的边全部照亮需要的最小花费 代码: #include <stdio.h> #include <string.h> const double eps = 1e-6;

UVA 14000 Lighting System Design(DP)

You are given the task to design a lighting system for a huge conference hall. After doing a lot of calculation & sketching, you have figured out the requirements for an energy-efficient design that can properly illuminate the entire hall. According