@ljt12138
2017-06-10T17:13:03.000000Z
字数 1996
阅读 867
dp&分类讨论
#include <bits/stdc++.h>
using namespace std;
int n, m;
char str[17][305];
int lft[17], rgt[17];
int dp[17][2];
int main()
{
memset(dp, -1, sizeof dp);
scanf("%d%d", &n, &m), m += 2;
int beg = -1;
for (int i = 1; i <= n; i++) {
scanf("%s", str[i]+1);
lft[i] = rgt[i] = -1;
for (int j = 1; j <= m; j++) {
if (lft[i] == -1 && str[i][j] == '1') lft[i] = j;
if ( str[i][j] == '1') rgt[i] = j;
}
if (lft[i] != -1) beg = 1;
//cout << lft[i] << " " << rgt[i] << endl;
}
int bg = 1;
while (lft[bg] == -1 && bg <= n) bg++;
if (bg > n) { puts("0"); return 0; }
dp[bg][0] = rgt[bg]-1, dp[bg][1] = m-lft[bg];
// cout << dp[1][0] << " " << dp[1][1] << endl;
for (int i = bg+1; i <= n; i++) {
for (int j = 0; j <= 1; j++) {
dp[i][j] = 23333333;
int adi = 0;
if (lft[i] == -1) adi = 0;
else if (j == 0) adi = (rgt[i]-1)*2;
else adi = (m-lft[i])*2;
for (int k = 0; k <= 1; k++) {
if (j != k) dp[i][j] = min(dp[i][j], dp[i-1][k]+m);
else dp[i][j] = min(dp[i][j], dp[i-1][k]+adi+1);
}
// cout << dp[i][j] << " ";
}
// cout << endl;
}
cout << dp[n][0] << endl;
return 0;
}
二分/枚举k,然后排序...
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 100005;
int A[MAXN], C[MAXN], n, S;
int main()
{
scanf("%d%d", &n, &S);
for (int i = 1; i <= n; i++)
scanf("%d", &A[i]);
int ans = 0, ct = INT_MAX;
for (int k = 1; (long long)k*(k+1)*k/2 <= S && k <= n; k++) {
for (int i = 1; i <= n; i++) {
if (A[i]+1ll*i*k <= S)
C[i] = A[i]+i*k;
else C[i] = S+1;
}
sort(C+1, C+n+1);
int cnt = 0, mon = 0, i = 1;
while (cnt < k && mon+C[i] <= S && i <= n)
mon += C[i], cnt++, i++;
if (cnt == k) {
if (cnt > ans)
ans = cnt, ct = mon;
else if (cnt == ans)
ct = min(ct, mon);
}
}
if (ans == 0) { printf("0 0"); }
else printf("%d %d\n", ans, ct);
return 0;
}
阶梯博弈...只有(从叶子算第一层起)奇数层有影响。分类讨论换奇数/奇数,奇数/偶数和偶数/偶数。
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 100005;
int A[MAXN], C[MAXN], n, S;
int main()
{
scanf("%d%d", &n, &S);
for (int i = 1; i <= n; i++)
scanf("%d", &A[i]);
int ans = 0, ct = INT_MAX;
for (int k = 1; (long long)k*(k+1)*k/2 <= S && k <= n; k++) {
for (int i = 1; i <= n; i++) {
if (A[i]+1ll*i*k <= S)
C[i] = A[i]+i*k;
else C[i] = S+1;
}
sort(C+1, C+n+1);
int cnt = 0, mon = 0, i = 1;
while (cnt < k && mon+C[i] <= S && i <= n)
mon += C[i], cnt++, i++;
if (cnt == k) {
if (cnt > ans)
ans = cnt, ct = mon;
else if (cnt == ans)
ct = min(ct, mon);
}
}
if (ans == 0) { printf("0 0"); }
else printf("%d %d\n", ans, ct);
return 0;
}