Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined)【A,B,C,D】
呵呵哒,上分~
CodeForces 724A:
题意:
给你两个星期几,问连续两个月的头一天是否满足;
#include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> using namespace std; typedef long long LL; char s1[20],s2[20]; char s[7][11]= {"monday","tuesday","wednesday","thursday","friday","saturday","sunday"}; int n,m; void solve() { for(int i=0;i<7;i++) { if(strcmp(s1,s[i])==0) n=i+1; if(strcmp(s2,s[i])==0) m=i+1; } } void judge() { if(n>m) m+=7; m-=n; if(m==0||m==2||m==3) printf("YES\n"); else printf("NO\n"); } int main() { scanf("%s%s",s1,s2); solve(); judge(); return 0; }CodeForces 724B:
题意:
给你一个二维数组,每一行可以不超过一次移动,还可以不超过一次进行任意两列互换;
思路:
状压枚举两列互换的情况,然后对每一行判断,注意还要判断列没有换的情况(我也不知道需不需要,不过判了,没有wa,应该是需要的)
#include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> using namespace std; typedef long long LL; int a[25][25]; int tmp1[25]; int tmp2[25]; int n,m; bool Judge(int i,int x) { int f1=-1; int f2=-1; for(int j=0;j<m;j++) { if(x&(1<<j)) { if(f1==-1) f1=j; else f2=j; } } tmp2[f1]=tmp1[f1]=a[i][f2]; tmp2[f2]=tmp1[f2]=a[i][f1]; for(int j=0;j<m;j++) if(j!=f1&&j!=f2) tmp2[j]=tmp1[j]=a[i][j]; sort(tmp1,tmp1+m); int cnt=0; for(int j=0;j<m;j++) if(tmp1[j]!=tmp2[j]) { cnt++; if(cnt>2) return false; } return true; } bool judge_hang(int temp) { for(int i=0;i<n;i++) { if(!Judge(i,temp)) return false; } return true; } int main() { scanf("%d%d",&n,&m); for(int i=0;i<n;i++) for(int j=0;j<m;j++) scanf("%d",&a[i][j]); int N=1<<m; for(int i=0;i<N;i++) { int cnt=0; for(int j=0;j<m;j++) { if(i&(1<<j)) cnt++; } if(cnt==2||!i) { if(judge_hang(i)) { puts("YES"); return 0; } } } puts("NO"); return 0; }
CodeForces 724C:
题意:
射线从(0,0)往(1,1)方向,碰到墙反射,到四个角结束,给你n,m,k,n*m长宽,k点个个数,对于给出点,求最短到达时间,如果不能到达输出"-1"
思路:
暴力处理反弹有多少线,然后处理线上的点,可以预处理输入点的那些经过的线;
题意:
思路:
我们先考虑几个小问题:
我说在某个m个区间里,我找到了一个最小的,那我取它,行不行,比如m=3 对某个区间是abb,我取a,非常同情达理啊,那我换一下,这个区间是aaa的时候,我是取第一个a还是取第3个a,还是都取,其实这个时候问题就出来了,我们说对于一个答案串,aabbb,然后但是这里有3个aaa是吧,那我肯定得把a全取了啊,这样就能顶替b了,从而达到了字典序最小的字符串,但是如果我说,这个答案串是:aaaaaa那么对于这个区间来说(保证要取),那一定是只取一个就够了,多取只会增大字典序。
那么从而达到一个贪心策略:
对于一个[ i,i+m-1 ]这个区间必取,我们可以维护一个已取的最大值MAX,如果这个区间一有比MAX小的就直接拿过来,因为比最大的小啊,在一定程度上就可以把最大的顶开啊,比如现在已经找到aacc,那我已找到b,就拿过来aabcc,所以一定可以使大的元素的位置远离首位达到字典序变小,然后如果都是>=b呢?那么就取一个最远的,因为还是越少越好啊~
所以总的方案简略的说就是,先顶了最大,如果>=最大,那么就是最小的最远;
#include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> #include <math.h> #include <queue> #include <stack> using namespace std; #define mod 10007 #define INF 0x3f3f3f const double pi=acos(-1.0); typedef long long LL; const int MAX=100010; int n,m; char s[MAX]; int v[MAX]; int num[110]; int main() { int i,j,t,k; scanf("%d%s",&m,s); memset(v,0,sizeof(v)); memset(num,0,sizeof(num)); n=strlen(s); if(n<=m) { char x='z'; for(i=0; i<n; i++) { if(s[i]<x) x=s[i]; } printf("%c\n",x); return 0; } int l=0; char b='a'; for(i=0; i<n&&i<n-m+1; i++) { k=0; char a='z'; for(j=i; j<m+i; j++) { if(s[j]<b) { k=j; break; } if(s[j]<=a) { a=s[j]; k=j; } } if(s[k]>b) b=s[k]; num[s[k]-'a']++; v[k]=1; i=k; // printf("%d\n",k); } for(i=0; i<n; i++) { if(s[i]<b&&!v[i]) { num[s[i]-'a']++; } } for(i=0; i<26; i++) { while(num[i]) { char x=i+'a'; printf("%c",x); num[i]--; } } return 0; }