A.液晶屏裁剪
简单题。题目给出的长宽比例可能不是最简形式,所以首先化简,然后放大这个最小比例直到最大的比当前的长宽小于或等于。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <string>
#include <queue>
using namespace std;
int gcd(int x,int y)
{
int n;
while(y)
{
n=x%y;
x=y;
y=n;
}
return x;
}
int main()
{
int a, b, c, d;
while(scanf("%d %d %d %d", &a, &b, &c, &d) != EOF){
int x, y;
x = gcd(c, d);
c = c / x;
d = d / x;
x = a / c;
y = b / d;
x = x>y?y:x;
printf("%d %d\n", c * x, d * x);
}
return 0;
}
B.寻找最长合法括号序列
栈的应用,模拟题。首先得分析出,最长合法括号序列肯定是独立存在的,不存在两个最长合法括号序列重叠的情况,若重叠只能得到一个更长的序列。那么,我们需要一个辅助数组记录原序列当中哪些括号是被匹配过的,记1。然后再线扫这个辅助数组中最长连续的1的个数。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<iomanip>
#include<string>
#include<algorithm>
#include<ctime>
#include<stack>
#include<queue>
#include<vector>
#define N 1000005
using namespace std;
char str[N],sub[N];
stack<int> s;
int match(int a,int b)
{
if(str[a]=='('&&str[b]==')')
return 1;
return 0;
}
int main()
{
int len,i,j,l,start,end;
while(cin>>len>>str) {
memset(sub,0,sizeof(sub));
s.push(0);
for(i=1;i<len;i++) {
if(s.empty()) s.push(i);
else if(match(s.top(),i)){
sub[s.top()]=1;
sub[i]=1;
s.pop();
}
else
s.push(i);
}
i=start=end=l=0;
int num = 0;
while(i<len){
j=0;
while(i<len&&sub[i]==0)
i++;j=i;
while(i<len&&sub[i])
i++;
if(i-j>l){
l=i-j;
start=j;
end=i;
num=1;
}
else if(i-j==l){
num++;
}
}
printf("%d %d\n",end-start, num);
}
return 0;
}
C.角斗士
状态压缩DP。初看规模,n只有18,马上想到是dfs搜索或者是状态压缩dp。介于dp本人不是很强,比赛中没想出去,赛后看了一些别人的思路。
令数组dp[x]表示x在二进制上为1那些人活着的概率,比如现在只有3个人,那么dp[5]表示第一个人和第三个人活着的概率。由于比赛是随即选择两个人,那么每场比赛的概率为1 / C(活着的人的个数,2)。最终的概率应该是叠加上去。
那么状态转移方程为dp[i ^ (1 << j)] += dp[i] * win[j][k] / pos。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <string>
#include <queue>
using namespace std;
double pos[1 << 18];
double win[18][18];
int Cout1Num(int n)
{
int x = 0;
while(n){
x++;
n = n & (n - 1);
}
return x;
}
int main()
{
int n;
while (scanf("%d", &n) != EOF) {
int i, j, k;
for (i = 0; i < n; ++i) {
for (j = 0; j < n; ++j) {
scanf("%lf", &win[i][j]);
}
}
memset(pos, 0, sizeof(pos));
pos[(1 << n) - 1] = 1.0;
for (k = (1 << n) - 1; k > 0; --k) {
int c = Cout1Num(k);
int sum = c * (c - 1) / 2;
if (c == 1) {
continue;
}
for (i = 0; i < n; ++i) {
if ((k & (1 << i)) == 0) {
continue;
}
for (j = i + 1; j < n; ++j) {
if ((k & (1 << j)) == 0) {
continue;
}
pos[k ^ (1 << j)] += pos[k] * win[i][j] / sum;
pos[k ^ (1 << i)] += pos[k] * win[j][i] / sum;
}
}
}
for (i = 0; i < n; ++i) {
if(i)
printf(" ");
printf("%lf", pos[1 << i]);
}
printf("\n");
}
return 0;
}