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; }