zoukankan      html  css  js  c++  java
  • zoj1183 Scheduling Lectures

    这道题题意不想说了,跑了640ms,感觉水过去了,应该能通过单调队列优化,很长时间没碰已经不知道怎么写了,就说说现在的写法吧。

    状态定义很关键:dp[i][j]把前j个topic放在前i堂课.

    因为这道题中的topic不能跳,必须按顺序,那么我们可以用贪心先求出最少的课程数,凭感觉证明这个贪心的做法是准确的,且找不到反例。

    然后根据dp前后状态递推方程:

    dp[i][j]=max(dp[i][j],dp[i-1][k]+solve(k+1,j));(sum[k+1][j]<=L)

    我们显然写个二重循环,里面再找k的时候写个循环,最差情况是O(n^3),前两个循环顺序随便写,其中一种写法快200ms,但感觉能用单调队列来把那个找k的直接优化成O(1)的做法,以后想到再补。

    这道题格式很恶心,注意每个分块之间也要有空行。

    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<map>
    #include<iostream>
    #include<vector>
    #include<cstring>
    #include<queue>
    #include<string>
    using namespace std;
    int cas,cass;
    int l,c,n;
    int t[1005];
    int sum[1005];
    int dp[1005][1005];
    //dp[i][j]把前j个topic放在前i堂课
    //dp[i][j]=max(dp[i][j],dp[i-1][k]+solve(k+1,j));(sum[k+1][j]<=L)
    
    
    int solve(int x)
    {
        if(x==0)
       return 0;
       else if(x>0&&x<=10)
        return -c;
       else
        return (x-10)*(x-10);
    }
    int main()
    {
       // freopen("input.txt","r",stdin);
    
       scanf("%d",&cass);
       while(cass--)
       {
           int cas=1;
           while(scanf("%d",&n)==1&&n)
           {
               memset(sum,0,sizeof(sum));
               if(cas>=2)
                printf("
    ");
           printf("Case %d:
    
    ",cas++);
               scanf("%d%d",&l,&c);
               for(int i=1;i<=n;i++)
                {
                 scanf("%d",&t[i]);
                 if(i>1)
                    sum[i]=sum[i-1];
                 sum[i]+=t[i];
                }
                //贪心
                int ans=1;
                int cnt=0;
                for(int i=1;i<=n;i++)
                {
                    cnt+=t[i];
                    if(cnt>l)
                    {
                        ans++;
                        cnt=t[i];
                    }
                }
                //
                printf("Minimum number of lectures: %d
    ",ans);
                memset(dp,0X7f,sizeof(dp));
                dp[0][0]=0;
                for(int i=1;i<=ans;i++)
                    for(int j=1;j<=n;j++)
                    {
                        for(int k=j-1;k>=0&&sum[j]-sum[k]<=l;k--)
                        dp[i][j]=min(dp[i][j],dp[i-1][k]+solve(l-(sum[j]-sum[k])));
                    }
                     printf("Total dissatisfaction index: %d
    ",dp[ans][n]);
           }
           if(cass!=0)
           printf("
    ");
       }
    
    }
  • 相关阅读:
    正则表达式教程
    LINQ查询基本操作
    C# LINQ 基本操作实例
    Sublime Text 3 常用插件以及安装方法
    记一次矩阵列单元格合并和拆分组件的开发
    解析JavaScript函数的多种写法
    jQuery源码逐行分析学习02(第一部分:jQuery的一些变量和函数)
    jQuery源码逐行分析学习01(jQuery的框架结构简化)
    Vue IIS 403-Forbidden
    数组求和:二分递归
  • 原文地址:https://www.cnblogs.com/acliang/p/4928143.html
Copyright © 2011-2022 走看看