Educational Codeforces Round 106 (Rated for Div. 2)(A~C)(DP)
三题滚粗。(至少现在可以稳3题了呜呜)
A.Domino on Windowsill
本题是贪心的思想。如果第一行和第二行白色块的个数相同,那么全摆成竖的。白色块的数量最多为k1.如果不同就看他们之间的差值为多少,那么就能在插入差值除以2个白色块。即min(k1,k2)+abs(k1-k2)/2.黑色块同理
AC代码如下:
#include<cstdio> #include<cctype> #include<iostream> #include<vector> #include<algorithm> #include<queue> #include<cstring> #include<set> #define MAXN 10000005 using namespace std; typedef long long ll; int t,n,k1,k2,w,b; int main(){ scanf("%d",&t); while(t--){ scanf("%d%d%d%d%d",&n,&k1,&k2,&w,&b); int flag=0; int len1=max(k1,k2)-min(k1,k2); if(k1==k2){ if(w<=k1) flag=1; }else if(w<=min(k1,k2)+len1/2) flag=1; if(flag){ k1=n-k1; k2=n-k2; len1=max(k1,k2)-min(k1,k2); if(k1==k2){ if(b<=k1){ printf("YES\n"); continue; } }else if(b<=min(k1,k2)+len1/2){ printf("YES\n"); continue; } } printf("NO\n"); } return 0; }
B.Binary Removals
因为可以删不相邻的两个数,故对于101这种我们只需要留0即可。但我们也可以想到对于00这样的数就只能留0,对于11这样的数我们就只能留1。故当11出现在00之前时,就无法满足要求。因此只要判断是否存在11且11后面是否存在00即可。
AC代码如下:
#include<cstdio> #include<cctype> #include<iostream> #include<vector> #include<algorithm> #include<queue> #include<cstring> #include<set> #define MAXN 10000005 using namespace std; typedef long long ll; int t; char s[105]; int main(){ scanf("%d",&t); while(t--){ scanf("%s",s); int len=strlen(s); bool flag=0; for(int i=1;i<len;i++){ if(!flag){ if(s[i]==s[i-1]&&s[i]=='1') flag=1; }else if(s[i]==s[i-1]&&s[i]=='0'){ flag=2; printf("NO\n"); break; } if(i==len-1) printf("YES\n"); } } return 0; }
C.Minimum Grid Path(DP)
可以选择向右或向上,每次转向后走路的花费都会变。但是不难看出向右和向上是独立。故花费可以通过奇偶性分割成独立的两部分。我们令dp[i],为转向1~i次时到达终点的最小花费。那么就是令其中除了花费最小的那次其他都只走1步,剩下的由花费最少的那次走完即可。所以我们只需要找dp[i]+dp[i-1]的和最小的值即可。
AC代码如下:
#include<cstdio> #include<cctype> #include<iostream> #include<vector> #include<algorithm> #include<queue> #include<cstring> #include<set> #define MAXN 100005 using namespace std; typedef long long ll; int t,n; ll dp[MAXN];//��ʾ��һ������ֻתi�Σ�����Ҫ�����ٲ��� ll c[MAXN];//��ʾһ��ת�����·�Ļ��ѡ� ll pre[MAXN]; //ǰ��c1~ci��ǰ�� int main(){ scanf("%d",&t); while(t--){ scanf("%d",&n); scanf("%d",&c[1]); ll min1=c[1],min2=1e10; dp[1]=c[1]*n,dp[0]=0; pre[1]=c[1],pre[0]=0; int minans1,minans2; for(int i=2;i<=n;i++){ if(i&1){ scanf("%d",&c[i]); pre[i]=pre[i-2]+c[i]; if(min1>c[i]){ min1=c[i]; dp[i]=pre[i-2]+min1*(n-i/2); }else dp[i]=dp[i-2]-min1+c[i]; }else{ scanf("%d",&c[i]); pre[i]=pre[i-2]+c[i]; if(min2>c[i]){ min2=c[i]; dp[i]=pre[i-2]+min2*(n-i/2+1); }else dp[i]=dp[i-2]-min2+c[i]; } } ll ans=dp[1]+dp[2]; for(int i=1;i<=n-1;i++){ if((dp[i]+dp[i+1])<ans) ans=dp[i]+dp[i+1]; } printf("%lld\n",ans); } return 0; }

浙公网安备 33010602011771号