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("
    ");
       }
    
    }
  • 相关阅读:
    Neo.Geo系统视频硬件结构模拟 v2.0
    [原创] CPS1模拟器开发日志
    在博客园发现恶意群体回复打广告的
    [原创] Neo.Geo系统视频硬件结构模拟
    在 ASP.NET 中执行 URL 重写(读书笔记)
    c#中什么情况下用(int)什么情况下用Convert.ToInt32
    ASP.NET 例程完全代码版(7)——2.0中实现自配置的成员角色管理库
    Request.UrlReferrer详解
    .NET中获取电脑名、IP及用户名方法
    ASP.NET 2.0中的跨页面提交
  • 原文地址:https://www.cnblogs.com/acliang/p/4928143.html
Copyright © 2011-2022 走看看