第一次训练 密码:acmore
#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的更多相关文章
- 第二次训练 密码acmore
网址:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=26733#overview 贪心全场!!!! A题: #include <io ...
- 第三次训练 密码acmore
网站:CSUST7月23号 A题:大意是:一个N多边形,用红,绿,蓝三色给定点上色,要求划分成顶点颜色不同的三角形. 解析: 这道题是黑书上分治法的例题,还是比较巧的. 首先很容易发现当某种颜色的点只 ...
- 2018省赛赛第一次训练题解和ac代码
第一次就去拉了点思维很神奇的CF题目 2018省赛赛第一次训练 # Origin Title A CodeForces 607A Chain Reaction B CodeForces ...
- 2018天梯赛第一次训练题解和ac代码
随着评讲的进行代码和题解会逐步放上来 2018天梯赛第一次训练 1001 : 进制转换 Time Limit(Common/Java):1000MS/10000MS Memory Limit: ...
- Xeon 第一次训练赛 苏州大学ICPC集训队新生赛第二场(同步赛) [Cloned]
A.给出一个字符串,求出连续的权值递增和,断开以后权值重新计数,水题 #include<iostream> #include<string> #include<cmath ...
- 2020 NUC 19级第一次训练赛
感染(low) Description n户人家住在一条直线上,从左往右依次编号为1,2,...,n.起初,有m户人家感染了COVID-19,而接下来的每天感染的人家都会感染他家左右两家的人,问t天后 ...
- YOLO2 (3) 快速训练自己的目标
1快速训练自己的目标 在 YOLO2 (2) 测试自己的数据 中记录了完整的训练自己数据的过程. 训练时目标只有一类 car. 如果已经执行过第一次训练,改过一次配置文件,之后仍然训练同样的目标还是只 ...
- 使用fastai训练的一个性别识别模型
在学习了python中的一些机器学习的相关模块后,再一次开始了深度学习之旅.不过与上次的TensorFlow框架不同,这一次接触的是fast.ai这样一个东西.这个框架还不稳定,网上也没有相关的中文文 ...
- opencv_haar分类器的训练
本文为作者原创,未经允许不得转载:原文由作者发表在博客园: http://www.cnblogs.com/panxiaochun/p/5345412.html 因为工作的原因,本人需要用到分类器来检测 ...
随机推荐
- 转:Java 计算2个时间相差多少年,多少个月,多少天的几种方式
日期比较对象 DayCompare 代码用到了 lombok ,如果不用,其实就是把getter / setter方法自己写一遍,还有构造方法. @Data @Builder public stat ...
- jquery-layer弹出框
样式1: 代码: 前台jsp: $("#add_table").bind("click",function(){ layer.open({ type: 2, t ...
- oc46--nonatomic, retain
// // Person.h #import <Foundation/Foundation.h> #import "Room.h" #import "Car. ...
- 托管在IIS上的wcf,在启动的时候,写log
https://blogs.msdn.microsoft.com/wenlong/2006/01/11/how-to-initialize-hosted-wcf-services/ Using App ...
- servlet中的中文乱码问题
老师总会说道:学完这个知识点,我们来谈谈中文乱码问题. 乱码的问题总是无处不在,处理不好会给用户带极差的用户体验. 那么我们来记录一下servlet中的乱码问题吧! 1.服务器向客户端响应时出现的乱码 ...
- 第11课 Git GUI程序的基本功能
11-1 Git GUI程序的基本操作
- T - Amusing Joke(map)
Problem description So, the New Year holidays are over. Santa Claus and his colleagues can take a re ...
- Cloudera Manager安装之利用parcels方式(在线或离线)安装单节点集群(包含最新稳定版本或指定版本的安装)(添加服务)(Ubuntu14.04)(四)
.. 欢迎大家,加入我的微信公众号:大数据躺过的坑 免费给分享 同时,大家可以关注我的个人博客: http://www.cnblogs.com/zlslch/ 和 http ...
- 【java基础】(1)Java的权限修饰符(public,protected,default,private)
访问权限修饰符权限从高到低排列是public ,protected ,default, private. 一.根据“是否是同包”.“是否是子类”分为4中情况+本类 5种情况 二.把 同包中的子类 ...
- electron 学习
index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset=&quo ...