您的位置:首页 > 其它

2011湖南第七届省赛

2014-07-19 11:39 225 查看
http://vjudge.net/contest/view.action?cid=50014#problem/E

E - Box Game

思路:

这种简单的博弈,一般的思路是:有一个必输态(P),还有很多必胜态(N),一个状态要是可以达到一个必输态的话,当前的这种状态为必胜态,如果只能到达必胜态的话,当前状态必为必输状态。.本题当面对最大值为2时为必N(胜态),那么3为p(必输),4为N,5为N,6为N,7为P,8为N。。。。。。13为N,14为N,15为P。。。。。。

4一定能到3,5一定能到3,6一定能到3,7只能到4、5、6状态(全为必胜态),则7为P。这么一直推导下去会发现只要面临了2^n-1时,则必输。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>

int main() {
int n;
while(~scanf("%d",&n),n){
int tmp=n+1;
bool flag=false;
while(tmp>=2){
if(tmp%2!=0){
flag=true;
}
tmp=tmp>>1;
}
if(flag==false) printf("Bob\n");
else printf("Alice\n");
}
return 0;
}


B - Counting Game

题意:
要求第m个人,举k次手时,数报道了什么地方。(一定会有解的,因为很多以七开头的数,数大到一定的程度后每个人一定能聚到一百次手的,比如7 x x x x,那么一定能让100个人,每个人都举一百次手)

在m出可能数字满足以下规律,注意在最左边和最右边的地方要特殊处理一下。

#include<stdio.h>
#define MAX 1<<30
bool deal(int num) {
bool flag=false;
if(num%7==0) {
flag=true;
} else {
int tmp=num;
while(tmp) {
if(tmp%10==7) {
flag=true;
break;
}
tmp=tmp/10;
}
}
if(flag==true) return true;
else return false;
}
int main() {
int n,m,k;
int num[50000];
while(~scanf("%d %d %d",&n,&m,&k),(n||m||k)) {
int cnt=2;
int ans=0;
num[1]=m;
if(deal(m)==true)ans++;
for(int i=2; i<MAX; i++) {
if(i%2==0) {
if(n==m)continue;//如果在最右边那么要跳过,否则就会数2次(题目要求下一轮从第n-1‡人开始数)
num[cnt]=num[cnt-1]+2*(n-m);//num[cnt-1]+(n-m)+((n-1)-m+1) (n-m)向左边的要数的数,((n-1)-m+1)从最左边回到m要数的数
if(deal(num[cnt])==true) ans++;
cnt++;
} else if(i%2==1){
if(m==1) continue;//如果在最左边,则在下一轮的时候,应该跳过,否则会数2次(题目要求下一轮从第2人开始数)
num[cnt]=num[cnt-1]+2*m-2;
if(deal(num[cnt])==true) ans++;
cnt++;
}
if(ans==k) {
printf("%d\n",num[cnt-1]);
break;
}
}
}
return 0;
}


C - Polyomino Composer

由于本题的数据很小,一看就是暴力做就好了。
由于无论什类型的图形,一定有一个最左上方的点,又由于本题的图形,是有两小图形只能通过平移,且没有重叠的组成的。那么同时找到大图形的最左上角的点,

对应的标记。然后再从没有被标记的点钟找到最左上的点,就能进行第二个图形的处理了。

#include<stdio.h>
#include<string.h>
#define MAX 25
char poly1[MAX][MAX];
char poly2[MAX][MAX];
bool mark[MAX][MAX];
struct Node{
int x;
int y;
}p1,p2;
int main() {
int n,m;
while(~scanf("%d %d",&n,&m),(n||m)){
memset(mark,false,sizeof(mark));
int num1=0;
int num2=0;
bool flag=false;
for(int i=0;i<n;i++){
scanf("%s",poly1[i]);
for(int j=0;j<n;j++){
if(poly1[i][j]=='*') num1++;
}
}
for(int i=0;i<m;i++){
scanf("%s",poly2[i]);
for(int j=0;j<m;j++){
if(poly2[i][j]=='*'){
num2++;
}
}
}//找p1
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(poly1[j][i]=='*'){
p1.x=j;
p1.y=i;
flag=true;
break;
}
}
if(flag==true) break;
}//找p2
flag=false;
for(int i=0;i<m;i++){
for(int j=0;j<m;j++){
if(poly2[j][i]=='*'){
p2.x=j;
p2.y=i;
flag=true;
break;
}
}
if(flag==true) break;
}
for(int i=0;i<m;i++){
for(int j=0;j<m;j++){
if(poly2[i][j]=='*'){
mark[p1.x+i-p2.x][p1.y+j-p2.y]=true;
}
}
}
flag=false;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(poly1[j][i]=='*'&&mark[j][i]==false){
p1.x=j;
p1.y=i;
flag=true;
break;
}
}
if(flag==true){
break;
}
}
for(int i=0;i<m;i++){
for(int j=0;j<m;j++){
if(poly2[i][j]=='*'&&mark[p1.x+i-p2.x][p1.y+j-p2.y]==false){
mark[p1.x+i-p2.x][p1.y+j-p2.y]=true;
}
}
}

int cnt=0;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(poly1[i][j]=='*'&&mark[i][j]==true){
cnt++;
}
}
}
if(cnt==num1&&num1==2*num2){
printf("1\n");
}else{
printf("0\n");
}
}
return 0;
}

/**
4 3
**..
**..
..**
..**
...
.**
.**

4 3
.*..
**..
***.
**..
*..
*..
**.

4 3
.***
.***
.***
....
...
.**
.**

4 2
*...
*...
...*
...*
*.
*.
3 2
...
**.
**.
**
**

**/
K - RMQ with Shifts

这是一道线段树模板题。

处理字符串的时候要注意,我们队两个人都犯了同样的错误:

void dealstr(char tmp[]){
int len=strlen(tmp);
cnt=0;
for(int i=6;i<len-1;){
op[cnt++]=tmp[i]-'0';
i=i+2;
}
}


再有就是要注意在shift以后要,要变换原来的数组。

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
using namespace std;
#define MAX 423456//4*n
int num[MAX];
int segTree[MAX];
char a[100];
int op[100];
int cnt=0;
int n,m;
void dealstr(char tmp[]){
int len=strlen(tmp);
cnt=0;
int ans=0;
for(int i=6;i<len;i++){
if((tmp[i]-'0')>=0&&(tmp[i]-'0')<=9){
ans=ans*10+(tmp[i]-'0');
}else{
op[cnt]=ans;
ans=0;
cnt++;
}
}
}
void build(int l,int r,int root){
if(l==r){
segTree[root]=num[l];
return;
}else{
int mid=(l+r)/2;
build(l,mid,root*2);
build(mid+1,r,root*2+1);
if(segTree[root*2]<segTree[root*2+1]){
segTree[root]=segTree[root*2];
}else{
segTree[root]=segTree[root*2+1];
}
}
}
void update(int l,int r,int root,int pos,int ind){
if(l==r){
segTree[root]=num[ind];
return;
}
int mid=(l+r)/2;
if(pos<=mid) update(l,mid,root*2,pos,ind);
else update(mid+1,r,root*2+1,pos,ind);
segTree[root]=min(segTree[root*2],segTree[root*2+1]);
}
void shift(){
for(int i=0;i<cnt;i++){
update(1,n,1,op[i],op[(i+1)%cnt]);
}
int tmp=num[op[0]];
for(int i=1;i<cnt;i++){
num[op[i-1]]=num[op[i]];
}
num[op[cnt-1]]=tmp;
}
int query(int l,int r,int from,int to,int root){
int p1,p2;
if(l>to||r<from){
return -1;
}
if(l>=from&&r<=to){
return segTree[root];
}
int mid=(l+r)/2;
p1=query(l,mid,from,to,root*2);
p2=query(mid+1,r,from,to,root*2+1);
if(p1==-1) return p2;
if(p2==-1) return p1;
if(p1<=p2) return p1;
return p2;
}
int main() {
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&num[i]);
}
build(1,n,1);
while(m--){
scanf("%s",a);
cnt=0;
dealstr(a);
if(a[0]=='q'){
int ans=query(1,n,op[0],op[1],1);
printf("%d\n",ans);
}else{
shift();
}
}
return 0;
}
/***
7 5
6 2 4 8 5 1 4
query(3,7)
shift(2,4000,5799,7)
query(1,4)
shift(1,2)
query(2,2)
****/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: