学会设计状态+注意初始化的边界(1421)

来源:互联网 发布:机器人软件下载 编辑:程序博客网 时间:2024/06/12 18:45

搬寝室

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 23146    Accepted Submission(s): 7912


Problem Description
搬寝室是很累的,xhd深有体会.时间追述2006年7月9号,那天xhd迫于无奈要从27号楼搬到3号楼,因为10号要封楼了.看着寝室里的n件物品,xhd开始发呆,因为n是一个小于2000的整数,实在是太多了,于是xhd决定随便搬2*k件过去就行了.但还是会很累,因为2*k也不小是一个不大于n的整数.幸运的是xhd根据多年的搬东西的经验发现每搬一次的疲劳度是和左右手的物品的重量差的平方成正比(这里补充一句,xhd每次搬两件东西,左手一件右手一件).例如xhd左手拿重量为3的物品,右手拿重量为6的物品,则他搬完这次的疲劳度为(6-3)^2 = 9.现在可怜的xhd希望知道搬完这2*k件物品后的最佳状态是怎样的(也就是最低的疲劳度),请告诉他吧.
 

Input
每组输入数据有两行,第一行有两个数n,k(2<=2*k<=n<2000).第二行有n个整数分别表示n件物品的重量(重量是一个小于2^15的正整数).
 

Output
对应每组输入数据,输出数据只有一个表示他的最少的疲劳度,每个一行.
 

Sample Input
2 11 3
 

Sample Output
4

注意排序的重要性,限制了选择的多样性,如果选择第i项,必然和前一项配对。DP方程为:dp[i][j]=min(dp[i-1][j],dp[i-2][j-1]+(s[i]-s[i-1])*(s[i]-s[i-1]))。学会设计状态。初始化一定要小心边界,因为取min,所以必然设定为INF,但是DP[i][0]只能等于0。

/*------------------Header Files------------------*/#include <iostream>#include <cstring>#include <string>#include <cstdio>#include <algorithm>#include <cstdlib>#include <ctype.h>#include <cmath>#include <stack>#include <queue>#include <map>#include <vector>#include <limits.h>using namespace std;/*------------------Definitions-------------------*/#define LL long long#define PI acos(-1.0)#define INF 0x3F3F3F3F#define MOD 10E9+7/*---------------------Work-----------------------*/int s[2050];int dp[2050][1500];bool cmp(int a,int b){return a<b;}void work(){int n,k;while(cin>>n>>k){for(int i=1;i<=n;i++)scanf("%d",s+i);sort(s+1,s+n+1,cmp); //排序为了DP方程的正确性for(int i=1;i<=n;i++)for(int j=1;j<=n/2;j++)dp[i][j]=INF;for(int i=0;i<=n;i++) //注意初始化dp[i][0]=0;for(int i=2;i<=n;i++){for(int j=1;j<=i/2;j++){dp[i][j]=min(dp[i-1][j],dp[i-2][j-1]+(s[i]-s[i-1])*(s[i]-s[i-1]));}}printf("%d\n",dp[n][k]);}}/*------------------Main Function------------------*/int main(){//freopen("test.txt","r",stdin);//freopen("cowtour.out","w",stdout);//freopen("cowtour.in","r",stdin);work();return 0;}

Employment Planning

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 4576    Accepted Submission(s): 1918


Problem Description
A project manager wants to determine the number of the workers needed in every month. He does know the minimal number of the workers needed in each month. When he hires or fires a worker, there will be some extra cost. Once a worker is hired, he will get the salary even if he is not working. The manager knows the costs of hiring a worker, firing a worker, and the salary of a worker. Then the manager will confront such a problem: how many workers he will hire or fire each month in order to keep the lowest total cost of the project.
 

Input
The input may contain several data sets. Each data set contains three lines. First line contains the months of the project planed to use which is no more than 12. The second line contains the cost of hiring a worker, the amount of the salary, the cost of firing a worker. The third line contains several numbers, which represent the minimal number of the workers needed each month. The input is terminated by line containing a single '0'.
 

Output
The output contains one line. The minimal total cost of the project.
 

Sample Input
3 4 5 610 9 110
 

Sample Output
199

dp[i][j]表示前i个月还剩j个人的最小费用。注意这道题的意思是只能在月初hire/fire。

<span style="font-weight: normal;">/*------------------Header Files------------------*/#include <iostream>#include <cstring>#include <string>#include <cstdio>#include <algorithm>#include <cstdlib>#include <ctype.h>#include <cmath>#include <stack>#include <queue>#include <map>#include <vector>#include <limits.h>using namespace std;/*------------------Definitions-------------------*/#define LL long long#define PI acos(-1.0)#define INF 0x3F3F3F3F#define MOD 10E9+7#define MAX 500050/*---------------------Work-----------------------*/int need[15];int dp[15][150];void work(){int n;while(cin>>n,n){int hire,salary,fire;scanf("%d%d%d",&hire,&salary,&fire);int max_need=-INF;for(int i=1;i<=n;i++){scanf("%d",&need[i]);max_need=max(max_need,need[i]);}for(int i=need[1];i<=max_need;i++)dp[1][i]=i*(salary+hire);int money;for(int i=2;i<=n;i++){for(int j=need[i];j<=max_need;j++){dp[i][j]=INF; //因为要取小,所以要无穷大,设在这里可以避免全局初始化 for(int k=need[i-1];k<=max_need;k++){if(j>=k) dp[i][j]=min(dp[i][j],dp[i-1][k]+(j-k)*hire+j*salary);else dp[i][j]=min(dp[i][j],dp[i-1][k]+(k-j)*fire+j*salary);}}}int Min=INF;for(int j=need[n];j<=max_need;j++)Min=min(Min,dp[n][j]);printf("%d\n",Min);}}/*------------------Main Function------------------*/int main(){//freopen("test.txt","r",stdin);//freopen("cowtour.out","w",stdout);//freopen("cowtour.in","r",stdin);work();return 0;}</span>


0 0
原创粉丝点击