#include <cstdio>
#include <cstring>
#define M 100010
#define INF 0x7FFFFFFF
#define Min(a,b) (a < b ? a : b)
#define mem0(f) memset(f,0,sizeof(f))
char a[][];
char b[][];
int num[][]; int get_num(int a,int b,int c,int d)
{
int number = ;
for(int i = ; i <= ; i++)
{
if((a & << (i - )) == ) //位运算,1<<(i-1)=(i-1)*2
{
number++;
num[][i]++;
num[][i - ]++;
num[][i + ]++;
num[][i]++;
}
if((b & << (i - )) == )
{
number++;
num[][i]++;
num[][i - ]++;
num[][i + ]++;
num[][i]++;
num[][i]++;
}
if((c & << (i - )) == )
{
number++;
num[][i]++;
num[][i - ]++;
num[][i + ]++;
num[][i]++;
num[][i]++;
}
if((d & << (i - )) == )
{
number++;
num[][i]++;
num[][i]++;
num[][i + ]++;
num[][i - ]++;
}
}
return number;
} void flip()
{
for(int i = ; i <= ; i++)
for(int j = ; j <= ; j++)
if(num[i][j] % != )
{
if(b[i][j] == 'w')
b[i][j] = 'b';
else
b[i][j] = 'w';
}
} int checkb()
{
int flag1 = ;
int flag2 = ;
for(int i = ; i <= ; i++)
for(int j = ; j <= ; j++)
if(b[i][j] == 'w')
return ;
return ;
} int checkw()
{
int flag1 = ;
int flag2 = ;
for(int i = ; i <= ; i++)
for(int j = ; j <= ; j++)
if(b[i][j] == 'b')
return ;
return ;
} int main()
{
int ans = INF;
for(int i = ; i <= ; i++)
scanf("%s",a[i] + );
for(int i = ; i < ; i++)
for(int j = ; j < ; j++)
for(int k = ; k < ; k++)
for(int p = ; p < ; p++)
{
memcpy(b,a,sizeof(a));
mem0(num);
int number = get_num(i,j,k,p);
flip();
if(checkb() || checkw())
ans = Min(ans,number);
}
if(ans == INF)
printf("Impossible\n");
else
printf("%d\n",ans);
return ;
}

网址:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=26732#overview

先讲一下整体情况,A,B题是差不多的题型,DFS,A题枚举也行一共2^16种可能。

C题没什么好说的,暴力求解。

D题,待我再研究下题目。

E题,貌似数据有问题.....

F题,本来用母函数做,结果一句:Your program should be able to handle up to 100 coins.差点秒杀全场,结果证明可以用暴力求解,另DP。

总的一句:暴力专场!!!!!!

A题,4X4的黑白翻转棋,输出最小的能全变成一种颜色的步数,不能则输出:impossible。

#include<stdio.h>
#include<iostream>
using namespace std;
int chess[][];
int c=;
void build()//将棋盘的颜色以标记化
{
char c;
int i,j;
for(i=;i<;i++)
for(j=;j<;j++)
{
cin>>c;
if(c=='w')
chess[i][j]=;
else
chess[i][j]=;
}
}
void turn(int x,int y)//翻转
{
if(x>=&&x<=&&y>=&&y<=)
chess[x][y]=!chess[x][y];
}
void flip(int s)//一个棋子变化,周围四个都要变化
{
int i=s/;//行
int j=s%;//列
turn(i,j);
turn(i+,j);
turn(i,j+);
turn(i-,j);
turn(i,j-);
}
int complete()//判断棋盘是否变成同一的颜色
{
int i,j,s1=;
for(i=;i<;i++)
for(j=;j<;j++)
s1+=chess[i][j];
if(s1%)
return ;
else
return ;
}
void dfs(int s,int b)//进行深搜.s代表当前的方格,b代表翻转的方格数
{
if(complete())//如果是同一颜色
{
if(c>b)
c=b;
return;
}
if(s>=)//如果遍历完
return;
dfs(s+,b); //不是很理解这一步及以下3步
flip(s);
dfs(s+,b+);
flip(s);
}
int main()
{
build();//将棋盘的颜色以标记化
dfs(,);
if(c==)//由于翻转次数最多为4*4*2=32次
printf("Impossible\n");
else
printf("%d\n",c);
return ;
}

上面这种方法待我看过DFS再来看,再做标注。
另一种代码:

#include<iostream>
#include<cstdio>
using namespace std; int map[][],step,flag=; void turn(int i,int j)//转换
{
map[i][j]=!map[i][j];
if(i>)
map[i-][j]=!map[i-][j];
if(i<)
map[i+][j]=!map[i+][j];
if(j>)
map[i][j-]=!map[i][j-];
if(j<)
map[i][j+]=!map[i][j+];
} int range()//判定表格是否全部一样
{
int i,j;
for(i=;i<;i++)
for(j=;j<;j++)
if(map[i][j]!=map[][])
return ;
return ;
} int DFS(int i,int j,int dp)//深搜
{
if(dp==step)
{
flag=range();
return ;
}
if(flag||i==) return ;
turn(i,j);
if(j<)
DFS(i,j+,dp+);
else
DFS(i+,,dp+);
turn(i,j);
if(j<)
DFS(i,j+,dp);
else
DFS(i+,,dp);
return ;
}
int main()
{
int i,j;
char a;
for(i=;i<;i++)
{
for(j=;j<;j++)
{
scanf("%c",&a);
if(a=='b')
map[i][j]=;
else
map[i][j]=;
}
getchar();
}
for(step=;step<=;step++)
{
flag=;
DFS(,,);
if(flag) break;
}
if(flag)
printf("%d\n",step);
else
printf("Impossible\n");
return ;
}

等我看了DFS再来写。。。。Orz

另一种,用枚举+位运算:

/*
解题思路:
由于输入的字符串中只含'b'或'w',而且只有16个字符,所以可以将输入的字符串理解为二进制表达式;
将这个字符串转换成一个10进制数字。然后bfs的同时,再用位运算(^)来改变它周围的数字(字符)。
具体见程序:
*/
#include <stdio.h>
#include <queue>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
using namespace std;
struct node
{
int step;
int val;
};
int st,used[];
int bfs()
{
int i;
queue<node> q;
node tmp;
tmp.step=;
tmp.val=st;
q.push(tmp);
memset(used,,sizeof(used));
used[st]=;
while(!q.empty())
{
node cur=q.front();
q.pop();
if(cur.val==||cur.val==(<<)-)
return cur.step;
for(i=;i<;i++)
{
node next=cur;
int tx=i/,ty=i%;
//下面的4个if就是用来判断是否越界,如果没有,那么改变该节点(中心节点的邻节点);
if(tx->=) next.val^=<<(-(*(tx-)+ty));
if(tx+<) next.val^=<<(-(*(tx+)+ty));
if(ty->=) next.val^=<<(-(*tx+ty-));
if(ty+<) next.val^=<<(-(*tx+ty+));
next.val^=<<(-i);
if(!used[next.val])
{
next.step++;
used[next.val]=;
q.push(next);
}
}
}
return -;
}
int main()
{
int i;
char s[];
while(scanf("%s",s)!=EOF)
{
st=;
for(i=;i<;i++) scanf("%s",s+*i);
//将输入的字符串转换成一个10进制数。
for(i=;i<;i++)
{
st<<=;
st|=(s[i]=='b');
}
int ans=bfs();
if(ans==-) printf("Impossible\n");
else printf("%d\n",ans);
}
return ;
}

枚举+位运算:这个比较好理解  1 #include <cstdio>

 #include <cstring>
#define M 100010
#define INF 0x7FFFFFFF
#define Min(a,b) (a < b ? a : b)
#define mem0(f) memset(f,0,sizeof(f))
char a[][];
char b[][];
int num[][]; int get_num(int a,int b,int c,int d)
{
int number = ;
for(int i = ; i <= ; i++)
{
if((a & << (i - )) == ) //位运算,1<<(i-1)=1*2^(i-1)
{
number++;
num[][i]++;
num[][i - ]++;
num[][i + ]++;
num[][i]++;
}
if((b & << (i - )) == )
{
number++;
num[][i]++;
num[][i - ]++;
num[][i + ]++;
num[][i]++;
num[][i]++;
}
if((c & << (i - )) == )
{
number++;
num[][i]++;
num[][i - ]++;
num[][i + ]++;
num[][i]++;
num[][i]++;
}
if((d & << (i - )) == )
{
number++;
num[][i]++;
num[][i]++;
num[][i + ]++;
num[][i - ]++;
}
}
return number;
} void flip()
{
for(int i = ; i <= ; i++)
for(int j = ; j <= ; j++)
if(num[i][j] % != )
{
if(b[i][j] == 'w')
b[i][j] = 'b';
else
b[i][j] = 'w';
}
} int checkb()
{ for(int i = ; i <= ; i++)
for(int j = ; j <= ; j++)
if(b[i][j] == 'w')
return ;
return ;
} int checkw()
{ for(int i = ; i <= ; i++)
for(int j = ; j <= ; j++)
if(b[i][j] == 'b')
return ;
return ;
} int main()
{
int ans = INF;
for(int i = ; i <= ; i++)
scanf("%s",a[i] + );
for(int i = ; i < ; i++)
for(int j = ; j < ; j++)
for(int k = ; k < ; k++)
for(int p = ; p < ; p++)
{
memcpy(b,a,sizeof(a));
mem0(num);
int number = get_num(i,j,k,p);
flip();
if(checkb() || checkw())
ans = Min(ans,number);
}
if(ans == INF)
printf("Impossible\n");
else
printf("%d\n",ans);
return ;
}

B题和A题很像

大神的代码:

/*

参考高手的高效解法:
> 证明:要使一个为'+'的符号变为'-',必须其相应的行和列的操作数为奇数;可以证明,如果'+'位置对应的行和列上每一个位置都进行一次操作,则整个图只有这一'+'位置的符号改变,其余都不会改变.
> 设置一个4*4的整型数组,初值为零,用于记录每个点的操作数,那么在每个'+'上的行和列的的位置都加1,得到结果模2(因为一个点进行偶数次操作的效果和没进行操作一样,这就是楼上说的取反的原理),然后计算整型数组中一的
> 个数即为操作数,一的位置为要操作的位置(其他原来操作数为偶数的因为操作并不发生效果,因此不进行操作)
*********************************
此上证其可以按以上步骤使数组中值都为‘-’
********************************
在上述证明中将所有的行和列的位置都加1后,在将其模2之前,对给定的数组状态,将所有的位置操作其所存的操作数个次数,举例,如果a[i][j]==n,则对(i,j)操作n次,当所有的操作完后,即全为‘-’的数组。
其实就是不模2的操作,作了许多的无用功。
以上的操作次序对结果无影响,如果存在一个最小的步骤,则此步骤一定在以上操作之中。(简单说下:因为以上操作已经包含了所有可改变欲改变位置的操作了)
而模2后的操作是去掉了所有无用功之后的操作,此操作同样包含最小步骤。
但模2后的操作去掉任何一个或几个步骤后,都不可能再得到全为‘-’的。(此同样可证明:因为操作次序无影响,先进行最小步骤,得到全为‘-’,如果还剩下m步,则在全为‘-’的数组状态下进行这m步操作后还得到一个全为
‘-’的数组状态,此只能是在同一个位置进行偶数次操作,与前文模2后矛盾,所以m=0),因此模2后的操作即为最小步骤的操作。
*/
#include <iostream>
using namespace std; bool mark[][];
char s[][]; int main()
{
int i,j,k;
int ci[],cj[];
int nas = ;
memset(mark,,sizeof(mark));
for(i = ;i < ;i++)
cin >> s[i];
for(i = ;i < ;i++)
for(j = ;j < ;j++)
{
char c = s[i][j];
if(c == '+')
{
mark[i][j] = !mark[i][j];
for(k = ;k < ;k++)
{
mark[i][k] = !mark[i][k];
mark[k][j] = !mark[k][j];
}
} }
for(i = ;i < ;i++)
for(j = ;j < ;j++)
if(mark[i][j] == true)
{
ci[nas] = i + ;
cj[nas] = j + ;
nas ++;
}
printf("%d\n",nas);
for(i = ;i < nas;i++)
{
printf("%d %d\n",ci[i],cj[i]);
}
return ;
}

这个懂了,NB,在输入+-的时候略坑,上面的s[i]是一次输入一行,就不存在把回车当做一个字符了。时间为  94MS

这样输入更好:时间为32MS

for(i=0;i<3;i++)
for(j=0;j<=4;j++)
scanf("%c",&map2[i][j]);
for(j=0;j<4;j++)
scanf("%c",&map2[3][j]);
我的代码~~~我是取2的余数决定有没有翻:
 #include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int main()
{
int map[][],i,j,sum=,k;
char map2[][];
memset(map,,sizeof(map));
for(i=;i<;i++)
for(j=;j<=;j++)
scanf("%c",&map2[i][j]);
for(j=;j<;j++)
scanf("%c",&map2[][j]);
getchar();
for(i=;i<;i++)
for(j=;j<;j++)
{
char c=map2[i][j];
if(c=='+')
{
map[i][j]++;
for(k=;k<;k++)
{
map[i][k]++;
map[k][j]++;
}
}
}
for(i=;i<;i++)
for(j=;j<;j++)
if(map[i][j]%==)
sum++;
printf("%d\n",sum);
for(i=;i<;i++)
for(j=;j<;j++)
if(map[i][j]%==)
printf("%d %d\n",i+,j+);
return ;
}
C题.....:
#include<iostream>
#include<string.h>
#include<stdio.h>
using namespace std;
int main()
{
int n,i,a[],b[],maxn,map[][],j,k,q;
while(~scanf("%d",&n)&&n)
{
memset(map,,sizeof(map));
int x,y,x1,y1;
maxn=;
scanf("%d%d",&x,&y);
for(i=;i<n;i++)
{
scanf("%d%d",&a[i],&b[i]);
map[a[i]][b[i]]=;
}
scanf("%d%d",&x1,&y1);
for(i=;i<=x-x1+;i++)
for(j=;j<=y-y1+;j++)
{
q=;
for(k=;k<n;k++)
if(a[k]>=i&&a[k]<i+x1&&b[k]>=j&&b[k]<j+y1&&map[a[k]][b[k]]==)
q++;
if(q>maxn)
maxn=q;
}
printf("%d\n",maxn);
}
return ;
}

建立一个地图,有树的地方标记为1。再暴力就行了。

D题:表示还是不知道方法,但是要注意double 会失精度。

大神代码:

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
int main()
{
double a, b, c, A, B, C;
int N, s, xo, yo, zo, X, Y, Z,XO,YO,ZO, re, sum;
scanf("%d", &N);
while(N--)
{
scanf("%d%lf%lf%lf", &s, &a,&b,&c);
sum=s;
A=b*c;
B=a*c;
C=a*b;
xo=floor(s*A/(A+B+C));
yo=floor(s*B/(A+B+C));
zo=floor(s*C/(A+B+C));
XO=xo->?xo-:;
YO=yo->?yo-:;
ZO=zo->?zo-:;
for(X=XO; X<=xo+; X++)
{
for(Y=YO; Y<=yo+; Y++)
{
for(Z=ZO;Z<=zo+&&X+Y+Z<=s; Z++)
{
re=floor(X*a);
if(floor(Y*b)<re)
re=floor(Y*b);
if(floor(Z*c)<re)
re=floor(Z*c);
re+=(s-X-Y-Z);
if(re>sum)
sum=re;
}
}
}
printf("%d\n", sum);
}
return ;
}

真心不知道他是怎么分配的。。。

另一种方法,注意精度。

 #include <algorithm>
#include <stdio.h>
#include<string.h>
#define Max(a,b) (a > b ? a : b)
int num[];
int main()
{
int n;
int bb,bbb,cc,ccc,dd,ddd;
int d,b,c;
int a;
scanf("%d",&n);
while(n--)
{
memset(num,,sizeof(num));
scanf("%d%d.%d%d.%d%d.%d",&a,&bb,&bbb,&cc,&ccc,&dd,&ddd);
b = (bb * + bbb);
c = (cc * + ccc);
d = (dd * + ddd);
int ans = a;
for(int i=;i<=a;i++)
{
if((num[])*b<=(num[])*c&&(num[])*b<= (num[])*d) //一块钱一块钱放,放在收益最小的栏里
num[]++;
else if((num[])*c<=(num[])*b&&(num[])*c<=(num[])*d)
num[]++;
else if((num[])*d<=(num[])*c&&(num[])*d<=(num[])* b)
num[]++;
if((num[])*b<=(num[])*c&&(num[])*b<=(num[])*d)
ans= Max(ans,(num[]*b)/+(a-i));
else if((num[])*c<=(num[])*b&&(num[])*c<=(num[])*d)
ans= Max(ans,(num[]*c)/+(a-i));
else if((num[])*d<=(num[])*c&&(num[])*d<=(num[])*b)
ans= Max(ans,(num[]*d)/+(a-i)); //最后和本金相比,取最大值
}
printf("%d\n",ans);
}
return ;
}

F:

 #include <stdio.h>
int main()
{
int a,b,c,d,e,num,n;
while(~scanf("%d",&n))
{
num=;
for(a=;a<=n;a++)
for(b=;b*<=n-a;b++)
for(c=;c*<=n-a-*b;c++)
for(d=;d*<=n-a-*b-*c;d++)
{
e=n-a-*b-*c-*d;
if(e%==&&a+b+c+d+e/<=)
num++;
}
printf("%d\n",num);
}
return ;
}

暴力也能过= =:109ms

第一次训练 密码:acmore的更多相关文章

  1. 第二次训练 密码acmore

    网址:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=26733#overview 贪心全场!!!! A题: #include <io ...

  2. 第三次训练 密码acmore

    网站:CSUST7月23号 A题:大意是:一个N多边形,用红,绿,蓝三色给定点上色,要求划分成顶点颜色不同的三角形. 解析: 这道题是黑书上分治法的例题,还是比较巧的. 首先很容易发现当某种颜色的点只 ...

  3. 2018省赛赛第一次训练题解和ac代码

    第一次就去拉了点思维很神奇的CF题目 2018省赛赛第一次训练 # Origin Title     A CodeForces 607A Chain Reaction     B CodeForces ...

  4. 2018天梯赛第一次训练题解和ac代码

    随着评讲的进行代码和题解会逐步放上来 2018天梯赛第一次训练 1001 : 进制转换 Time Limit(Common/Java):1000MS/10000MS     Memory Limit: ...

  5. Xeon 第一次训练赛 苏州大学ICPC集训队新生赛第二场(同步赛) [Cloned]

    A.给出一个字符串,求出连续的权值递增和,断开以后权值重新计数,水题 #include<iostream> #include<string> #include<cmath ...

  6. 2020 NUC 19级第一次训练赛

    感染(low) Description n户人家住在一条直线上,从左往右依次编号为1,2,...,n.起初,有m户人家感染了COVID-19,而接下来的每天感染的人家都会感染他家左右两家的人,问t天后 ...

  7. YOLO2 (3) 快速训练自己的目标

    1快速训练自己的目标 在 YOLO2 (2) 测试自己的数据 中记录了完整的训练自己数据的过程. 训练时目标只有一类 car. 如果已经执行过第一次训练,改过一次配置文件,之后仍然训练同样的目标还是只 ...

  8. 使用fastai训练的一个性别识别模型

    在学习了python中的一些机器学习的相关模块后,再一次开始了深度学习之旅.不过与上次的TensorFlow框架不同,这一次接触的是fast.ai这样一个东西.这个框架还不稳定,网上也没有相关的中文文 ...

  9. opencv_haar分类器的训练

    本文为作者原创,未经允许不得转载:原文由作者发表在博客园: http://www.cnblogs.com/panxiaochun/p/5345412.html 因为工作的原因,本人需要用到分类器来检测 ...

随机推荐

  1. android graphic(15)—fence

    为何须要fence fence怎样使用 软件实现的opengl 硬件实现的opengl 上层使用canvas画图 上层使用opengl画图 下层合成 updateTexImage doComposeS ...

  2. luogu2320 鬼谷子的钱袋

    题目大意 鬼谷子决定将自己的金币数好并用一个个的小钱袋装好,以便在他现有金币的支付能力下,任何数目的金币他都能用这些封闭好的小钱的组合来付账.求钱袋数最少,并且不有两个钱袋装有相同的大于1的金币数的装 ...

  3. bzoj 1026 [ SCOI2009 ] windy数 —— 数位DP

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1026 蛮简单的数位DP,预处理 f[i][j] 表示 i 位数,以 j 开头的 windy ...

  4. pandas把多个sheet读进一个DataFrame

    #!/usr/bin/python import pandas as pd import collections df_dict = pd.read_excel('c:\data\machines.x ...

  5. 87.Ext_菜单组件_Ext.menu.Menu

    转自:https://blog.csdn.net/lms1256012967/article/details/52574921 菜单组件常用配置: /* Ext.menu.Menu主要配置项表: it ...

  6. python 内存泄露的诊断

    对于一个用 python 实现的,长期运行的后台服务进程来说,如果内存持续增长,那么很可能是有了"内存泄露" 一.内存泄露的原因 对于 python 这种支持垃圾回收的语言来说,怎 ...

  7. Node.js+express 4.x 入门笔记

    一.新建node项目并实现访问 二.在express4.x下,让ejs模板文件,使用扩展名为html的文件 三.实现路由功能 四.session使用 五.页面访问控制及提示 六.代码下载地址 一.新建 ...

  8. [转]RDLC 动态列

    本文转自:http://blog.csdn.net/luochengbang/article/details/9964551 很久没有写博客了,关于动态列,国内很少资料有介绍动态列的,所想写点心得给哥 ...

  9. poj1958-汉诺四塔问题(三种方法)

    链接:http://poj.org/problem?id=1958 大意:汉诺塔升级版,四根柱子,n个盘子,求最少移动次数: 两种方法 递推or递归(当然还有思路3--打表) 思路1:递推(或者DP? ...

  10. ACM_名字的价值

    名字的价值 Time Limit: 2000/1000ms (Java/Others) Problem Description: 集训终于开始了,参加集训的人很多,也就有很多名字,集训组织者发现了一件 ...