• 2014.7.8模拟赛【笨笨当粉刷匠】|bzoj1296 [SCOI]粉刷匠


     笨笨太好玩了,农田荒芜了,彩奖用光了,笨笨只好到处找工作,笨笨找到了一份粉刷匠的工作。笨笨有n条木板需要被粉刷。每条木板被分成m个格子,每个格子要被刷成红色或蓝色。笨笨每次粉刷,只能选择一条木板上一段连续的格子,然后涂上一种颜色,已知每个格子最多只能被粉刷一次。

        如果笨笨只能粉刷t次,他最多能正确粉刷多少格子。

        一个格子如果未被粉刷或被粉刷成错误颜色,就算粉刷错误。

    【输入格式】

        第一行三个数n,m,t;

        接下来n行,每行一个长度为m的字符“0”表示红色,"1"表示蓝色。

    【输出格式】

        一个整数,最多能正确粉刷的格子数。

        Sample input

        3 6 3

        111111

        000000

        001100

        Sample output

        16

        100%数据范围满足1≤n,m≤50;0≤t≤2500。


    这是bzoj上原题啊……bzoj1296 [SCOI]粉刷匠

    就是两个dp

    首先,注意到每一行的状态都是和其他行独立的,也就是说,只要你知道了这一行的状态,其他行长什么样无所谓。

    所以我们可以先把每一行分开处理

    s[i][j][0/1]表示第i行前j个有多少个0/1

    g[i][j][k]表示第i行前j个涂k次能正确涂色的格子个数

    g[i][j][k] = max( g[i][j][k] , g[i][L][k-1]+max(s[i][j][0] - s[i][L][0],s[i][j][1] - s[i][L][1]))。

    意思是枚举第k-1次涂到L时,在L到j之间涂0或1是否比当前优,效率n^4。我曾经尝试写n^3求第i行涂j次的最优解,可惜貌似不行。

    最后发现再令h[i][j]表示第i行涂j次的最优解,f[i][j]表示前i行涂j次的最优解,则f[i][j]=max(f[i][j] , f[i-1][j-k] + h[i][k])。但是边界范围要考虑,可以一整行都不刷。否则在bzoj上能A,但是模拟赛上只有90。

    #include<cstdio>
    #include<iostream>
    using namespace std;
    char ch;
    int n,m,t;
    int h[101][101];
    int g[101][101][101];
    int s[101][101][2];
    int f[101][3001];
    bool map[101][101];
    int main()
    {
    	freopen("draw.in","r",stdin);
    	freopen("draw.out","w",stdout);
    	scanf("%d%d%d",&n,&m,&t);
    	for (int i=1;i<=n;i++)
    	  for (int j=1;j<=m;j++)
    	    {
    	    	cin>>ch;
    	    	if (ch=='1') map[i][j]=1;
    	    	s[i][j][0]=s[i][j-1][0]+(ch=='0');
    	    	s[i][j][1]=s[i][j-1][1]+(ch=='1');
    	    }
    	for (int i=1;i<=n;i++)
    	  for (int j=1;j<=m;j++)
    	    for (int k=1;k<=m;k++)
    	      for (int l=0;l<j;l++)
    	      g[i][j][k]=max(g[i][j][k],g[i][l][k-1]+max(s[i][j][0]-s[i][l][0],s[i][j][1]-s[i][l][1]));
    	for (int i=1;i<=n;i++)
    	  for (int j=1;j<=m;j++)
    	    for (int k=1;k<=m;k++)
    	  	h[i][j]=max(h[i][j],g[i][k][j]);
    	for (int i=1;i<=n;i++)
    	  for (int j=1;j<=t;j++)
    	    for (int k=0;k<=j;k++)
    	    f[i][j]=max(f[i][j],f[i-1][j-k]+h[i][k]);
    	printf("%d",f[n][t]);
    }
    
    ——by zhber,转载请注明来源
  • 相关阅读:
    FZU Problem 2150 Fire Game
    HTTP协议认识
    GitHub
    设计模式学习笔记(一)——面向对象设计模式与原则
    信息安全系统设计基础第九周学习总结
    信息安全系统设计基础第八周期中总结
    家庭作业二
    信息安全系统设计基础第七周学习总结
    家庭作业
    信息安全系统设计基础第六周学习总结
  • 原文地址:https://www.cnblogs.com/zhber/p/4036067.html
Copyright © 2020-2023  润新知