codeforces-D-Nastya and Scoreboard

codeforces-D-Nastya and Scoreboard

传送门:https://codeforces.com/contest/1341/problem/D

题意:

一个n个数码位的分数板,每一个数码位都是一个七段数码管,现在给出每个数码位的显示情况,问再点亮k段数码管的话能显示的最大的数是多少,如果不能构成一串数字,就输出-1.

是一个加了许多剪枝的dfs

因为是要求能显示的最大的数是多少,所以应该从9往后贪心的选

记录下 cnt[i][j] 为第i个数想变成j需要点亮多少段数码管,如果变不成 cnt[i][j]=-inf

然后问题就转换成了 在cnt[i][j](i>=1&&i<=n)(j>=0&&j<=9) 的每一个 i 里选一个数,使他们相加恰好等于k,而且这个选择组成的n位数还是最大的

因为要求最大,所以越往前数应该往大了选,i==1时如果可以变成9,那就是9,9不行,就找8,7,6……,然后i==2,9,8,7……

那怎么实现,很眼熟,当年搜索不就是这么玩的吗

所以搞一个dfs就行

然后你就会Time limit exceeded on test 7

确实,n=2000呢,递归必超时呀

dfs(int n,int now(当前到了第几个数),int ls(到现在为止已经点亮了多少数码管),int k)

那就优化一下吧,首先ls>k指定是不行的(因为你想让他恰好等于k,你这都超了)

然后我们想,因为对于后面的每一个 i 都是要在 cnt[i][j] 里选一个出来

那如果剩下的k-ls小于(后面每一个 i 的 cnt[i][j] 最小值的和)是肯定不行的 ,这样即使后面每个数都取最小还是有i取不到数

同理,k-ls大于(后面每一个 i 的 cnt[i][j] 最大值的和)也不行,因为即使每个数都取最大k还是会剩下

 最后希望你们不要像我一样老犯憨批错误 快乐AC 乌拉~

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define lowbit(a) ((a)&-(a))
#define clean(a,b) memset(a,b,sizeof(a))
const int mod = 1e9 + 7;
const int inf=0x3f3f3f3f;
const int maxn = 2e7+10;

inline int read(){char c=getchar();int tot=1;while ((c<'0'|| c>'9')&&c!='-') c=getchar();if (c=='-'){tot=-1;c=getchar();}
int sum=0;while (c>='0'&&c<='9'){sum=sum*10+c-'0';c=getchar();}return sum*tot;}

int _;
//////////////////////////////////////////////////////////////////////////
int mp[2009][19];
int d[19][19];
int cnt[2009][19];
int suma[2009],sumi[2009];
vector<int>num;
int solve(int n,int now,int ls,int k)
{ 
    if(ls>k) return 0;
    if(k-ls<sumi[now]) return 0;
    if(k-ls>suma[now]) return 0;
    if(n==now-1&&ls==k) return 1;
    else if(n==now-1&&ls!=k) return 0;
    for(int i=9;i>=0;i--)
    {
        if(cnt[now][i]>=0) 
        {
 //           if(n-now>ls-cnt[now][i]) continue;
            if(solve(n,now+1,ls+cnt[now][i],k)) 
            {
                num.push_back(i);
                return 1;
            }
        }
    }
    return 0;
}
//////////////////////////////////////////////////////////////////////////

int main()
{
    d[0][1]=1,d[0][2]=1,d[0][3]=1,d[0][5]=1,d[0][6]=1,d[0][7]=1;
    d[1][3]=1,d[1][6]=1;
    d[2][1]=1,d[2][3]=1,d[2][4]=1,d[2][5]=1,d[2][7]=1;
    d[3][1]=1,d[3][3]=1,d[3][4]=1,d[3][6]=1,d[3][7]=1;
    d[4][3]=1,d[4][4]=1,d[4][6]=1,d[4][2]=1;
    d[5][1]=1,d[5][2]=1,d[5][4]=1,d[5][6]=1,d[5][7]=1;
    d[6][1]=1,d[6][2]=1,d[6][4]=1,d[6][5]=1,d[6][6]=1,d[6][7]=1;
    d[7][1]=1,d[7][3]=1,d[7][6]=1;
    d[8][1]=1,d[8][2]=1,d[8][3]=1,d[8][4]=1,d[8][5]=1,d[8][6]=1,d[8][7]=1;
    d[9][1]=1,d[9][2]=1,d[9][3]=1,d[9][4]=1,d[9][6]=1,d[9][7]=1;
    int n=read();
    int k=read();
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=7;j++)
        scanf("%1d",&mp[i][j]);
    }
    for(int i=1;i<=n;i++)
    {
        for(int k=0;k<=9;k++)
        {
            for(int j=1;j<=7;j++)
            {
                if(d[k][j]==1&&mp[i][j]==0) cnt[i][k]++;
                else if(d[k][j]==0&&mp[i][j]==1) cnt[i][k]=-inf;
            }
        }
    }
    for(int i=n;i>=1;i--)
    {
        int maxx=0,minn=7;
        for(int j=0;j<=9;j++)
        {
            if(cnt[i][j]>=0) 
            {
                minn=min(minn,cnt[i][j]);
                maxx=max(maxx,cnt[i][j]);
            }
        }
        suma[i]=suma[i+1]+maxx;
        sumi[i]=sumi[i+1]+minn;
    }
    solve(n,1,0,k);
    if(num.size()==0) printf("-1");
    for(int i=num.size()-1;i>=0;i--) printf("%d",num[i]);
    printf("\n");
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/YangKun-/p/12768168.html
今日推荐