此处有目录↑
题目链接:http://codeforces.com/gym/100553
Problem A. Alter Board
题目大意:给定一个n*m的棋盘,棋盘有黑白两种颜色,且任意相邻的两个格子中的颜色不一样,每次可以选一个矩形,使其中每个格子的颜色换成另一种颜色,求最少几步能将棋盘变成一种颜色,并输出方案。
每次只对偶数行和偶数列转换,则答案最小
#include <cstdio>
#include <cstring>
using namespace std;
int n,m;
int main() {
freopen("alter.in","r",stdin);
freopen("alter.out","w",stdout);
while(2==scanf("%d%d",&n,&m)) {
printf("%d\n",n/2+m/2);
for(int i=2;i<=n;i+=2) {
printf("%d %d %d %d\n",i,1,i,m);
}
for(int j=2;j<=m;j+=2) {
printf("%d %d %d %d\n",1,j,n,j);
}
}
return 0;
}
Problem B. Burrito King (贪心)
题目大意:一个煎饼可由n种原料组成,第i种原料由3个数描述:g[i]、a[i] 和 b[i],表示第i种原料不能超过g克,要求确定每种原料的数量s[i],使得∑s[i]*a[i]>=A,且∑s[i]*b[i]<=B,若存在多种情况,则要求∑s[i]*a[i]最大。
要答案最优,则定有 ∑s[i]*b[i]==B 或者 ∑g[i]*b[i]<=B,由于可以去实数克,所以每次必定取a[i]/b[i]最大的,所以排序后贪心即可
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN=100005;
const double EPS=0.000000001;
int n,cnt;
double tmp,sa,sb,A,B;
struct Node {
int index,g,a,b;
bool operator < (const Node& x) const {//按照a/b的降序排列
return a*x.b>x.a*b;
}
}ing[MAXN];
double ans[MAXN];
int main() {
freopen("burrito.in","r",stdin);
freopen("burrito.out","w",stdout);
while(3==scanf("%d%lf%lf",&n,&A,&B)) {
for(int i=1;i<=n;++i) {
scanf("%d%d%d",&ing[i].g,&ing[i].a,&ing[i].b);
ing[i].index=i;
}
sort(ing+1,ing+1+n);
memset(ans,0,sizeof(ans));
sa=sb=0;
cnt=0;
for(int i=1;i<=n;++i) {
tmp=ing[i].g*ing[i].b;
if(tmp+sb-EPS<=B) {
sa+=ing[i].g*ing[i].a;
sb+=tmp;
ans[ing[i].index]=ing[i].g;
}
else {
if(sb+EPS<B) {
ans[ing[i].index]=(B-sb)/ing[i].b;
sa+=ans[ing[i].index]*ing[i].a;
sb=B;
}
break;
}
}
if(sa+EPS<A) {
printf("-1 -1\n");
continue;
}
printf("%.8lf %.8lf\n%.8lf",sa,sb,ans[1]);
for(int i=2;i<=n;++i) {
printf(" %.8lf",ans[i]);
}
printf("\n");
}
return 0;
}
Problem F. Filter (模拟)
题目大意:01串的长度为m,哈希参数有f个,共有n个压缩成16进制的01串(16进制的第一个数字对应01串的0~3,以此类推【注意:权重低的位在前】,若m%4!=0,则16进制的最后一位的转成的01串共凑成m位即可),当且仅当用户u对所有的哈希参数使得下标为(u*a[1~f])%m的01串的位上为1,该01串包含用户u,共有q个用户,求哪些串至少包含一个用户?
直接按照题目意思模拟即可
#include <cstdio>
#include <cstring>
using namespace std;
int n,m,f,q,cur,cnt;
int bit[1005][1005];
int num[127],ans[1005];
long long a[105],u[1005];
char s[255];
bool flag;
int main() {
freopen("filter.in","r",stdin);
freopen("filter.out","w",stdout);
for(int i=0;i<=9;++i) {
num[i+'0']=i;
}
for(int i=0;i<6;++i) {
num[i+'a']=i+10;
}
while(2==scanf("%d%d",&m,&f)) {
for(int i=0;i<f;++i) {
scanf("%lld",a+i);
}
scanf("%d",&n);
for(int i=0;i<n;++i) {
scanf("%s",s);
int j=0;
for(;s[j+1]!='\0';++j) {
cur=num[s[j]];
for(int k=0;k<=3;++k) {//权重低的位在前
bit[i][(j<<2)+k]=cur%2;
cur/=2;
}
}
cur=num[s[j]];
for(int k=0;k<=(m+3)%4;++k) {//权重低的位在前
bit[i][(j<<2)+k]=cur%2;
cur/=2;
}
}
scanf("%d",&q);
for(int i=0;i<q;++i) {
scanf("%lld",u+i);
}
cnt=0;
for(int i=0;i<n;++i) {
for(int j=0;j<q;++j) {
flag=false;
for(int k=0;k<f;++k) {
if(bit[i][(u[j]*a[k])%m]!=1) {
flag=true;
break;
}
}
if(!flag) {
ans[cnt++]=i;
break;
}
}
}
printf("%d",cnt);
for(int i=0;i<cnt;++i) {
printf(" %d",ans[i]);
}
printf("\n");
}
return 0;
}
Problem J. Jokewithpermutation (DFS)
题目大意:给定一个1~n的排列,不含空格,输出拆分后的该排列。
由于大部分状态均不合法,所以直接dfs即可
貌似看到可以用DP做,再研究研究
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN=100005;
const double EPS=0.000000001;
char s[105];
int num[55],n,len;
bool vis[105];
bool dfs(int pos,int cnt) {//pos为当前位置,cnt表示已找出的数的个数
if(cnt==n) {//如果已找出n个数,并且字符串已遍历完,则当前结果合法
return pos==len;
}
int cur=s[pos]-'0';//一位数
if(!vis[cur]) {
vis[cur]=true;
num[cnt]=cur;
bool flag=dfs(pos+1,cnt+1);
vis[cur]=false;
if(flag) {
return true;
}
}
++pos;
if(pos==len) {
return false;
}
cur=cur*10+s[pos]-'0';//两位数
if(!vis[cur]) {
vis[cur]=true;
num[cnt]=cur;
bool flag=dfs(pos+1,cnt+1);
vis[cur]=false;
if(flag) {
return true;
}
}
return false;
}
int main() {
freopen("joke.in","r",stdin);
freopen("joke.out","w",stdout);
while(1==scanf("%s",s)) {
len=strlen(s);
n=len<=9?len:9+(len-9)/2;
vis[0]=true;
for(int i=1;i<=n;++i) {
vis[i]=false;
}
for(int i=n+1;i<105;++i) {//因为包含2位数,所以要将所有的2位数都初始化
vis[i]=true;
}
dfs(0,0);
printf("%d",num[0]);
for(int i=1;i<n;++i) {
printf(" %d",num[i]);
}
printf("\n");
}
return 0;
}
Problem K. Knockout Racing (模拟)
题目大意:有n辆车,每辆车的速度均为1m/s,第i辆车在a[i]~b[i]间往返跑,初始在a[i]。有m次询问,每次有3个数:x、y和t,表示求在开始的t秒后,有多少车在[x,y]内?
由于数据范围很小,直接模拟即可
#include <cstdio>
#include <cstring>
using namespace std;
const int MAXN=1005;
int n,m,tmp,t,x,y,coord,cnt;
int a[MAXN],b[MAXN],d[MAXN];
int getCoord(int i) {//貌似b[i]一定大于a[i],不过题意没有表明
if(d[i]>0) {
tmp=t%(d[i]<<1);
if(tmp<=d[i]) {
return a[i]+tmp;
}
return b[i]+d[i]-tmp;
}
else {
tmp=t%((-d[i])<<1);
if(tmp<=d[i]) {
return a[i]-tmp;
}
return a[i]-d[i]+tmp;
}
}
int main() {
freopen("knockout.in","r",stdin);
freopen("knockout.out","w",stdout);
while(2==scanf("%d%d",&n,&m)) {
for(int i=0;i<n;++i) {
scanf("%d%d",a+i,b+i);
d[i]=b[i]-a[i];
}
while(m-->0) {
cnt=0;
scanf("%d%d%d",&x,&y,&t);
for(int i=0;i<n;++i) {
coord=getCoord(i);
if(x<=coord&&coord<=y) {
++cnt;
}
}
printf("%d\n",cnt);
}
}
return 0;
}