题目链接
E - Dividing Chocolate
题意:给你h长,w宽矩阵 的黑白巧克力,1代表是白色,0是黑色
每次可以行切一刀,列切一刀,一切就要切到底的那种
问最多切多少刀,使得每一块巧克力中白色的数量小于等于k个
做法:经典做法了,最近牛客就遇到了两次,由于n特别小,那么对行进行暴力,切,然后对列进行贪心切即可。
我行的暴力用了二进制枚举
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
#define pi pair<int, int>
#define mk make_pair
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int N=1e3+10;
int a[20][N],n,m,k,b[20];
char s[N];
int sum[20][N];
struct node
{
int l1,l2;
}c[30];
int lenn;
int get(int l1,int r1,int l2,int r2)
{
return sum[l2][r2]-sum[l1-1][r2]-sum[l2][r1-1]+sum[l1-1][r1-1];
}
int run()
{
int r1=1,r2=1;
int t=0;
for(int i=1;i<=m;++i){
//printf("i:%d\n",i);
int flag=1;
//printf("i:%d r2:%d\n",i,r2);
for(int j=1;j<=lenn&&flag;++j){
if(get(c[j].l1,r1,c[j].l2,r2)<=k) {
continue;
}
else{
flag=0;
}
}
if(!flag){
if(r1==r2) return 1e9;
t++;
r1=r2;
r2++;
}
else ++r2;
}
return t;
}
int main()
{
cin>>n>>m>>k;
int ss=0;
rep(i,1,n)
{
cin>>s+1;
rep(j,1,m)
{
a[i][j]=s[j]-'0';
sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+a[i][j];
}
}
//printf("%d\n",get(1,3,3,5));
int len=(1<<n)-1;
int ans=1e9;
for(int j=0;j<=len;++j)
{
for(int k=0;k<n;++k){if((j>>k)&1) b[k+1]=1;else b[k+1]=0;}
int t=0;
lenn=0;
int pre=b[1],l2=1,l1=1;
for(int k=2;k<=n;++k){
if(b[k]==pre) l2++;
else{
t++;
c[++lenn]={l1,l2};
l1=k;l2=k;
pre=b[k];
}
}
c[++lenn]={l1,l2};
t+=run();
//printf("j:%d t:%d lenn:%d\n",j,t,lenn);
ans=min(ans,t);
}
printf("%d\n",ans);
}
F - Knapsack for All Segments
做法:设dp[i][j] 为当前序列以a[i]结尾时序列和为j的左下标之和。
那么答案就是
转移方程为:
用另一个数组f[i]维护这个就可以O(NS)的复杂度
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
#define pi pair<int, int>
#define mk make_pair
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int N=3e3+10;
const ll mod=998244353;
int a[N],n,s,len;
ll dp[N][N],f[N];
int main()
{
cin>>n>>s;
rep(i,1,n)
{
cin>>a[i];
}
for(int i=1;i<=n;++i){
dp[i][a[i]]=i;
for(int j=0;j<=s;++j){
if(j+a[i]>s) continue;
dp[i][j+a[i]]+=f[j];
dp[i][j+a[i]]%=mod;;
}
for(int j=0;j<=s;++j) f[j]+=dp[i][j],f[j]%=mod;
}
ll ans=0;
for(int i=1;i<=n;++i){
ans+=(1ll*n-i+1)*dp[i][s]%mod;
ans%=mod;
}
cout<<ans<<endl;
}