Google Code jam Qualification Round 2015 解题报告

来源:互联网 发布:php怎么写网页自动点击 编辑:程序博客网 时间:2024/06/05 07:21

Problem A. Standing Ovation

        题目说的是有许多观众,每个观众有一定的羞涩值,只有现场站起来鼓掌的人数达到该值才会站起来鼓掌,问最少添加多少羞涩值任意的人,才能使所有人都站起来鼓掌。

        贪心模拟一下就好,添加的人默认让他们羞涩值为0,扫一遍,让加到刚好够就行。

#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>#include <cmath>#include <stack>#include <vector>#include <deque>using namespace std;char str[1010];int main(){freopen("A-large.in","r",stdin);freopen("A-large.out","w",stdout);int t;cin>>t;int cas=0;while(t--){cas++;int MAX;cin>>MAX;scanf("%s",str);int len=strlen(str);int cnt=0;int ans=0;for(int i=0;i<len;i++){str[i]-='0';cnt+=str[i];if(cnt<i+1){int add = i+1-cnt;cnt+=add;ans+=add;}}printf("Case #%d: %d\n",cas,ans);}return 0;}


Problem B. Infinite House of Pancakes
        这个题很有意思。。说的是若干盘子上有一定量的食物,正常情况下,所有盘子上的食物每秒钟会减少1,或者你可以让某些秒变得特别,在特别的秒,盘子上的食物不会减少,但是你可以挑选一个有食物的盘子,移动部分或全部食物到另一个盘子上(空盘无限多)。目标是使所有食物尽快被吃完。

        稍微分析一下,很容易得出这样一个结论,先分再吃,也就是说,早分一定不会比晚分差。然后很容易想到贪心去分割食物最多的盘子,分一半给空盘。其实这样是不对的。。比如只有一个食物为9的盘子,分成3,3,3比分成4,5要优。

        我的解法是,首先只考虑只有一个盘子有食物的情况,dp预处理,dp(i,j)表示这个盘子有i个单位的食物,分为若干份,最大份食物量为j,至少需要多少次。

        过了几天回来看了下,发现自己非常2B,直接分就行了。。为什么还要去dp。所以这个题就是枚举一下找出最小值。

        然后就是贪心+枚举,先分再吃。枚举分的程度,即让所有盘子经过划分以后,食物最多的盘子不超过一个特定的值。详见代码。

#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>#include <cmath>#include <stack>#include <vector>#include <deque>#include <set>#include <queue>using namespace std;const int maxn = 1001;int p[maxn];int dp[maxn][maxn];int main(){freopen("B-large.in","r",stdin);freopen("B-large.out","w",stdout);//dp预处理 for(int i=2;i<maxn;i++){for(int j=1;j<i;j++){dp[i][j]=1000;for(int k=1;k<i;k++){dp[i][j]=min(dp[i][j],dp[i-k][j]+dp[k][j]+1);}}}int t;cin>>t;for(int cas=1;cas<=t;cas++){int d;cin>>d;int MAX=0;for(int i=1;i<=d;i++){scanf("%d",&p[i]);MAX=max(MAX,p[i]);}int ans=MAX;//枚举。即把所有食物量大于test的盘子分为若干份,使得不再出现食物量大于test的盘子 for(int test=1;test<=MAX;test++){int tmp=0;for(int i=1;i<=d;i++){tmp+=dp[p[i]][test];}tmp+=test;ans=min(ans,tmp);}printf("Case #%d: %d\n",cas,ans);}return 0;}

Problem C. Dijkstra

        这个题我只暴力过了小数据,大数据没想清楚怎么做。贴一下暴力代码。

#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>#include <cmath>#include <stack>#include <vector>#include <deque>#include <set>#include <queue>using namespace std;/*1-1i-2j-3k-4*/int tab[5][5]={{ 0, 0, 0, 0, 0},{ 0, 1, 2, 3, 4},{ 0, 2,-1, 4,-3},{ 0, 3,-4,-1, 2},{ 0, 4, 3,-2,-1}};int calc(int a,int b){bool flag=0;if(a<0){a=-a;flag=!flag;}if(b<0){b=-b;flag=!flag;}int re=tab[a][b];if(flag)re=-re;return re;}char str[10010];char re[10010][10010];int main(){freopen("C-small-attempt0.in","r",stdin);freopen("C-small-attempt0.out","w",stdout);int t;cin>>t;int cas=0;while(t--){cas++;int l,x;cin>>l>>x;scanf("%s",str);for(int i=0;i<l;i++){if(str[i]=='i')str[i]=2;else if(str[i]=='j')str[i]=3;else str[i]=4;}for(int i=1;i<x;i++){for(int j=0;j<l;j++){str[i*l+j]=str[j];}}int tot=l*x;if(tot<3){printf("Case #%d: NO\n",cas);continue;}for(int i=0;i<tot;i++){re[i][i]=str[i];for(int j=i+1;j<tot;j++){re[i][j]=calc(re[i][j-1],str[j]);}}bool ok=false;for(int i=0;i<tot-2;i++){for(int j=tot-1;j>i+1;j--){if(re[0][i]==2&&re[j][tot-1]==4&&re[i+1][j-1]==3){ok=1;}}}if(ok){printf("Case #%d: YES\n",cas);}else{printf("Case #%d: NO\n",cas);}}return 0;}

Problem D. Ominous Omino

        小数据其实就64中case,用脑子想一下打表交就可以了。大数据真心不会做Orz。

0 0