/* hihocoder 1631 : Cats and Fish
* [题意]:给出n条鱼,m值猫,给出每个猫吃鱼的速度a[i]给出(吃的快的优先吃)。
* 问x分钟后所剩的完整的鱼的数量,和不完整的鱼的数量。
*
* [分析]:由于吃鱼的速度不一样,将速度排序后,枚举1->x每个时间点,
* 确认在当前状态下,每条鱼是否能够完整的吃完一条鱼和当前时间点是否开始吃下一条鱼。
*
*
* [tricks]:
* 注意速度为1的情况,直接完整的吃掉一条鱼。
*
* [时间复杂度]:x*m*t
* */
#include <bits/stdc++.h>
#define ll long long
using namespace std;
void scan() {
#ifndef ONLINE_JUDGE
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
#endif
}
int n, m, x;
const int maxn = 1e6 + 7;
int a[maxn], vis[maxn];
int main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
scan();
//cout<<999<<endl;
while (cin >> n >> m >> x) {
for (int i = 1; i <= m; i++) cin >> a[i], vis[i] = 0;
sort(a + 1, a + 1 + m);
int p = n, q = 0;
for (int i = 1; i <= x; i++) {
if (p == 0) break;
for (int j = 1; j <= m; j++) {
if (i % a[j] == 0) {
if (a[j] == 1 && p) p--;
if (vis[j] && q) vis[j] = 0, q--;
} else {
if (!vis[j] && p) {
p--, q++, vis[j] = 1;
}
}
if (p == 0 && q == 0) break;
}
//cout<<"time: "<<i<<" || "<<p<<"***// "<<q<<endl;
if (p == 0 && q == 0) break;
}
// assert(p>=0),assert(q>=0);
cout << p << " " << q << endl;
}
return 0;
}
/* hihocoder 1632 : Secret Poems
* [题意]:蛇形取数,回旋填数;
*
* [分析]:针对每一斜行, 奇数行往上,偶数行往下,注意角标就ok了,认真模拟一下。
*
* [tricks]:
*
*
* [时间复杂度]:n*n
* */
#include <bits/stdc++.h>
#define ll long long
using namespace std;
void scan() {
#ifndef ONLINE_JUDGE
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
#endif
}
int n, m, x;
const int maxn = 1e3 + 7;
string ss[maxn], ans[maxn];
int main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
scan();
while (cin >> n) {
string ret;
for (int i = 0; i < n; i++) cin >> ss[i];
for (int i = 0; i < 2 * n; i++) {
if (i % 2) {
for (int j = i; j >= 0; j--) {
if (i - j < n && j < n)
ret += ss[i - j][j];
}
} else {
for (int j = 0; j <= i; j++) {
if (i - j < n && j < n)
ret += ss[i - j][j];
}
}
}
int l = 0, r = n - 1, up = 0, down = n - 1, cnt = 0, sz = ret.size();
while (cnt < sz) {
for (int i = l; i <= r; i++) ss[up][i] = ret[cnt++];
for (int i = up + 1; i <= down; i++) ss[i][r] = ret[cnt++];
for (int i = r - 1; i >= l; i--) ss[down][i] = ret[cnt++];
for (int i = down - 1; i >= up + 1; i--) ss[i][l] = ret[cnt++];
l++, r--, up++, down--;
}
// cout<<ret<<endl;
for (int i = 0; i < n; i++) cout << ss[i] << endl;
}
return 0;
}
/*HihoCoder 1636 : Pangu and Stones 区间DP
*
* 【题意】:给出n堆石子,每堆石子的数量为a[i],给出l,r,表示每进行一次合并,最少合并连续的l堆,最多合并连续r堆。
* 问:最后石子合并为1堆时所需的花费。花费:合并的石子的数量。
*
*
* 【分析】:很明显是个区间dp的经典问题,只不过是在这加了一个花费和堆的数量限制。
* dp[st][ed][k]:区间[st,ed]分成k堆的花费。
* 初始化:dp[st][st][1]=0;
* 由于最后的k==1,因此在划分区间[st,ed]的时候,每次将其划分成1,k-1块。
* 转移方程:dp[st][ed][k]=min(dp[st][ed][k],dp[st][mid][k-1]+dp[mid+1][ed][1]);
*
* 上述的转移方程是对于区间[st,ed]未加堆的限制下的之前的花费;
*
* 枚举堆的数量k-->[l-1,r-1],计算区间[st,ed]合并为1堆时的花费。
*
* 转移方程为:dp[st][ed][1] = min(dp[st][ed][1],dp[st][mid][k] + dp[mid + 1][ed][1] + sum[ed] - sum[st - 1]);
*
*
* [tricks]:
* 注意区间DP角标。
*
* [时间复杂度]:n^4
*
* */
#include <bits/stdc++.h>
#define ll long long
using namespace std;
void scan() {
#ifndef ONLINE_JUDGE
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
#endif
}
const int maxn = 110;
const int INF = 0x3f3f3f3f;
int dp[maxn][maxn][maxn], a[maxn], sum[maxn];
int n, l, r;
int main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
scan();
while (cin >> n >> l >> r) {
memset(dp, 0x3f, sizeof(dp));
for (int i = 1; i <= n; i++) {
cin >> a[i];
sum[i] = sum[i - 1] + a[i];
dp[i][i][1] = 0;;
}
for (int len = 2; len <= n; len++) {
for (int st = 1; st + len - 1 <= n; st++) {
int ed = st + len - 1;
for (int k = 2; k <= min(len, r); k++) {
for (int mid = st + k - 2; mid < ed; mid++) {
dp[st][ed][k] = min(dp[st][ed][k], dp[st][mid][k - 1] + dp[mid + 1][ed][1]);
}
}
for (int k = l - 1; k <= r - 1; k++) {
for (int mid = st + k - 1; mid < ed; mid++) {
dp[st][ed][1] = min(dp[st][ed][1], dp[st][mid][k] + dp[mid + 1][ed][1] + sum[ed] - sum[st - 1]);
}
}
}
}
cout << (dp[1][n][1] == INF ? 0 : dp[1][n][1]) << endl;
}
return 0;
}
感觉其它的题可以以后补吧。