2 条题解
-
1
全部 1ms!!
分享一种二分 + 贪心的高效做法喵。
在 n,m 数据达到 2000 时也是可以通过的哦。
点赞支持猫娘爆标喵。
#include<bits/stdc++.h> using namespace std; const int N = 100; char s[N][N]; int t[N]; vector<int> G[N]; // h:1, l:0 int n, m, X, Y, a[N], b[N]; int sum, mid; bool v[N]; bool cmp(int na, int nb) { return t[na] > t[nb]; } bool check() { sum = 0; memset(v, 0, sizeof(v)); if (X > Y) { for (int i = 1; i <= n; i ++) { a[i] = i; } sort (a + 1, a + n + 1, cmp); for (int i = 1; i <= n; i ++) { int now = a[i]; sum -= X; sum += t[now]; for (int j : G[now]) if (!v[j]) { v[j] = 1; sum -= Y; } if (sum >= mid) { return 1; } } return 0; } else { for (int j = 1; j <= m; j ++) { b[j] = j; } sort (b + 1, b + m + 1, cmp); for (int i = 1; i <= m; i ++) { int now = b[i]; sum -= Y; sum += t[now]; for (int j : G[now]) if (!v[j]) { v[j] = 1; sum -= X; } if (sum >= mid) { return 1; } } return 0; } } int main () { ios::sync_with_stdio(false); cin.tie(0); cin >> n >> m >> X >> Y; memset(t, 0, sizeof(t)); for (int i = 1; i <= n; i ++) { cin >> (s[i] + 1); for (int j = 1; j <= m; j ++) { if (s[i][j] == '1') { G[i].push_back(j + n); G[j + n].push_back(i); t[i] ++; t[j + n] ++; } } } int l = 0, r = 450, ans = 0; while (l <= r) { mid = (l + r) / 2; if (check()) { l = mid + 1; ans = mid; } else { r = mid - 1; } } cout << ans << "\n"; return 0; } -
0
为啥我翻了一下其他大佬的题解,他们都没一个用递归来写啊,我来发一篇递归的!
思路
注意到本题数据范围极小考虑使用递归算法。我们可以递归枚举选择那些蓝牌,然后计算选择这些蓝牌可以构造出牌堆的最大强度(枚举每个红牌,看看选上这个红牌能不能增加牌堆的强度,能就把它选上)。
代码
带有详细注释代码:
#include<bits/stdc++.h> using namespace std; int n,m,x,y,ans,f[22]; bool ff[22][22],fff[22][22]; char c; int js() { int sum=0; for(int i=1;i<=n;i++) { f[i]=0; //清空,否则一分没有(别问我怎么知道的) for(int j=1;j<=m;j++) { f[i]+=fff[i][j]; } } //对于每张红牌,算出选它能和多少张蓝牌组成好对。 for(int i=1;i<=n;i++) { sum+=max(0,f[i]-x); //如果选这张红牌能贡献答案,就选上它,否则不选。 } return sum; } void dfs(int now,int w) //参数分别表示现在枚举的是第几张蓝牌,现在选上的蓝牌已经对答案产生了多少负的贡献 { if(now==m+1) { ans=max(ans,js()-w); return ; } //如果已经选完了,就计算并更新答案。 for(int i=1;i<=n;i++) { fff[i][now]=ff[i][now]; } //如果选了这张蓝牌,就把这张蓝牌所对应的所有红牌标记为可用(前提是它本身就能组成好对) dfs(now+1,w+y); //继续递归 for(int i=1;i<=n;i++) { fff[i][now]=0; } //回溯 dfs(now+1,w); //不选 } int main() { cin>>n>>m>>x>>y; for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { cin>>c; ff[i][j]=c-'0'; } } //读入数据 dfs(1,0); //递归 cout<<ans; //输出 return 0; }
- 1
信息
- ID
- 12546
- 时间
- 1000ms
- 内存
- 600MiB
- 难度
- 7
- 标签
- 递交数
- 64
- 已通过
- 15
- 上传者