CF1341D

题目链接

题意的话给出了n个01串,1代表该位置是亮的,我们必须把m个位置变亮后且都是数字。求能组成的最大数字。每个位置代表的地方看题目给的图吧。

思路

明显的dp题,我们假设 d p [ i ] [ j ] dp[i][j] dp[i][j]表示前 i i i个数字花费 j j j次机会后能形成具体数字。那么其状态转移方程为: d p [ i ] [ j ] = d p [ i + 1 ] [ j + v a l [ k ] ] dp[i][j]=dp[i+1][j+val[k]] dp[i][j]=dp[i+1][j+val[k]]注意这里的 k k k表示的是第 i i i个数字变成 k k k所需的机会。那么当 d p [ 1 ] [ m ] = d p [ n + 1 ] [ 0 ] dp[1][m]=dp[n+1][0] dp[1][m]=dp[n+1][0]时也就是这 n n n个数字可以形成具体数字,而最大数字直接可以贪心得到,具体参考代码。

#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <queue>
#include <vector>
#include<map>
using namespace std;
const int N = 2e3+5;
typedef long long ll;
#define rep(i,a,b) for(i=(a);i<=b;i++)
#define pt(a) printf("%d\n",(a))
char a[N][N],b[10][10]={ "1110111", "0010010", "1011101", "1011011", "0111010", "1101011", "1101111", "1010010", "1111111", "1111011"};
int q[N][10];
bool solve(int x){
    bool flag = false;
    for(int i=0;i<10;i++){
        int sum=0;
        int j;
        for(j=0;j<7;j++){
            if(a[x][j]==b[i][j]) continue;
            else if(b[i][j]=='0') break;
            else sum++;
        }
        if(j==7) flag=true,q[x][i]=sum;
        else q[x][i]=-1;
    }
    return flag;
}
int ans[N],dp[N][N];
bool dfs(int x,int y){
    if(dp[x][y]!=-1) return dp[x][y];//记忆化爆搜,其中-1为未达点,0为失败点,1为成功点
    for(int i=9;i>=0;i--){
        if(q[x][i]!=-1){
            ans[x]=i;
            //printf("%d %d\n",x,i);
            if(y<q[x][i]) continue;
            if(dfs(x+1,y-q[x][i])){
                dp[x][y]=1;
                return true;
            }
        }
    }
    dp[x][y]=0;
    return false;
}
int main()
{
    int n,m,i,j,k,t=0,tot=0;
    scanf("%d %d",&n,&m);
    for(i=1;i<=n+2;i++) for(j=0;j<=m+2;j++) dp[i][j]=-1;
    for(i=1;i<=n;i++)scanf("%s",a+i);
    for(i=1;i<=n;i++){
        if(!solve(i)){
            printf("-1\n");
            return 0;
        }
    }
    dp[n+1][0]=1;
    if(dfs(1,m)){
        rep(i,1,n){
            printf("%d",ans[i]);
        }
        printf("\n");
    }
    else{
        printf("-1\n");
    }
    //system("pause");
    return 0;
}

总结

这题莫名其妙被我看成了分组背包,(太久没刷题,把背包定义都忘了分组背包,在同一个组里面最多取一个),而这一题必须取一个,所以wa是很正常的!当然如果有朋友发现可以写的话,可以留言让我修改哟。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值