AtCoder Beginner Contest 167 比赛人数11940 比赛开始后15分钟看到A题,之后每隔一分钟,看到一道题,在比赛开始后第21分钟看到所有题
AtCoder Beginner Contest 167 C Skill Up 满足C(n,1),C(n,2),C(n,3),......,C(n,n)的深搜dfs
总目录详见https://blog.csdn.net/mrcrack/article/details/104454762
在线测评地址https://atcoder.jp/contests/abc167/tasks/abc167_c
收获,在比赛中,独立悟出了 满足C(n,1),C(n,2),C(n,3),......,C(n,n)的深搜dfs 写法。
以样例1为例
Input:
3 3 10
60 2 2 4
70 8 7 9
50 2 3 9
Output:
120
枚举所有情况
(1)60 2 2 4
(2)70 8 7 9
(3)50 2 3 9
可有如下组合
(1)
(2)
(3)
(1)(2)
(1)(3)
(2)(3)
(1)(2)(3)
枚举上述组合,找出花费和值最小的情况。
以下为花费和值最小的情况
(2)70 8 7 9
(3)50 2 3 9
120 10>=10 10>=10 18>=10
AC代码如下
#include <cstdio>
#include <algorithm>
using namespace std;
int n,m,x;
int c[15],a[15][15],b[15],d[15],len,sum=100000000,cost;
void init(){//数据读取
int i,j;
scanf("%d%d%d",&n,&m,&x);
for(i=1;i<=n;i++){
scanf("%d",&c[i]);
for(j=1;j<=m;j++)
scanf("%d",&a[i][j]);
}
}
void dfs(int step){
int i,j,k;
if(step==len+1){//深搜结束条件
for(k=1;k<=m;k++)d[k]=0;//d[k]表示被选择的书店,在k列位置上的和
for(j=1;j<=len;j++)
for(k=1;k<=m;k++)
d[k]+=a[b[j]][k];//计算被选择的书店,在k列位置上的和
for(k=1;k<=m;k++)
if(d[k]<x)return;//不满足条件
cost=0;
for(j=1;j<=len;j++)cost+=c[b[j]];//计算花费
sum=min(sum,cost);//找最小值
return ;
}
for(i=b[step-1]+1;i<=n;i++)//找组合情况,就让后查找的位置越来越大,请注意i=b[step-1]+1
b[step]=i,dfs(step+1);
}
int main(){
init();
for(len=1;len<=n;len++)//len界定选择的书店的数量
b[0]=0,dfs(1);
if(sum==100000000)printf("-1\n");//没找到
else printf("%d\n",sum);
return 0;
}
类似的题目有:
AtCoder Beginner Contest 165 C Many Requirements 深搜dfs+生成非递减数组
AtCoder Beginner Contest 159 E Dividing Chocolate 二维前缀和+子矩阵和+深搜行+枚举列+注意行边界处理+注意列边界处理