signedmain(){ ios::sync_with_stdio(false), cin.tie(0); int n, m; while (cin >> n >> m) { int a[n], b[n]; double minn = 100; for (int i = 0; i < n; ++i) { cin >> a[i] >> b[i]; minn = min(minn, a[i] * 1.0 / b[i]); } cout << fixed << setprecision(7) << minn * m << endl; } // system("pause"); return0; }
题意:教室有 n 排座位,每有 m 个座位,将教室看做 n*m 的矩阵,. 代表一个空座位,* 代表座位被占用,现在需要在同一行或者同一列中找到连续的 k 个空座位,两种座位方式被认为是不同的当存在一个座位的位置不一样,请问有几种安排座位方式
思路:直接爆搜 TLE,注意因为是同一行或者同一列,所以我们可以借助前缀和,空座位存 1,被占座位存 0,分别为维护座位所在行和所在列的前缀和,那么如果某一行连续的 k 个座位的前缀和之差等于 k 则说明找到一个座位方式。还需要注意的是当 k 等于 1 的时候,只需要找横向或者竖向一个方向即可,否则会出现重复
int val[maxn], in[maxn], dp[maxn][30]; //dp[i][ch]表示经过i点是字母ch出现的最大次数 vector<int> G[maxn]; char s[maxn];
signedmain(){ // ios::sync_with_stdio(false), cin.tie(0); int n, m; cin >> n >> m; scanf("%s", s + 1); for (int i = 1; i <= n; ++i) { val[i] = s[i] - 'a' + 1; dp[i][val[i]] = 1; //初始化边界经过自身 } while (m--) { int x, y; cin >> x >> y; G[x].push_back(y); ++in[y]; } queue<int> que; for (int i = 1; i <= n; ++i) { if (in[i] == 0) que.push(i); } int cnt = 0; while (!que.empty()) { //每次取入度为0的点向其他向相邻的点走保证是一条路上的(相当于是从每条路的终点向起点走) int p = que.front(); que.pop(); ++cnt; //统计dp过的点数 for (auto e : G[p]) { //向其他方向走并转移dp for (int i = 1; i <= 26; ++i) { //各个字母 if (val[e] == i) //下一个点可以当前点+1 dp[e][i] = max(dp[e][i], dp[p][i] + 1); else dp[e][i] = max(dp[e][i], dp[p][i]); } --in[e]; if (in[e] == 0) que.push(e); } } if (cnt < n) //有环 cout << -1 << endl; else { int ans = 0; for (int i = 1; i <= n; ++i) { for (int j = 1; j <= 26; ++j) ans = max(ans, dp[i][j]); } cout << ans << endl; } // system("pause"); return0; }