做的 比较屎,但是还是涨rating了。。。
1001. HDU 5611 Baby Ming and phone number
http://acm.hdu.edu.cn/showproblem.php?pid=5611
直接按题意模拟,需注意以下闰年的判断方法(普通年,世纪年)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <queue>
using namespace std;
typedef long long LL;
char s[12];
int yes(int n,int y,int r){
if(y==0||y>12) return 0;
if(y==1||y==3||y==5||y==7||y==8||y==10||y==12){
if(r<=31) return 1;
return 0;
}
if(y!=2){
if(r<=30) return 1;
return 0;
}
if(n%4==0){
if(n%100==0){
if(n%400==0){
if(r<=29) return 1;
return 0;
}
else{
if(r<=28) return 1;
return 0;
}
}
else{
if(r<=29) return 1;
return 0;
}
}
if(r<=28) return 1;
return 0;
}
int main (){
int t,n,a,b;
scanf("%d",&t);
int ll=19800101,rr=20161231;
while(t--){
scanf("%d%d%d",&n,&a,&b);
LL ans=0;
while(n--){
//cout<<ans<<endl;
scanf("%s",s);
if(s[6]==s[7]&&s[7]==s[8]&&s[8]==s[9]&&s[9]==s[10]){
ans=ans+a;
continue;
}
if((s[6]-s[7]==1)&&(s[7]-s[8]==1)&&(s[8]-s[9]==1)&&(s[9]-s[10]==1)){
ans=ans+a;
continue;
}
if((s[6]-s[7]==-1)&&(s[7]-s[8]==-1)&&(s[8]-s[9]==-1)&&(s[9]-s[10]==-1)){
ans=ans+a;
continue;
}
int kk=0;
int n;
int y=(s[7]-'0')*10+(s[8]-'0');
int r=(s[9]-'0')*10+(s[10]-'0');
for(int i=3;i<=10;i++){
kk=kk*10+s[i]-'0';
if(i==6) n=kk;
}
if(kk<=rr&&kk>=ll&&yes(n,y,r)){
ans=ans+a;
continue;
}
ans=ans+b;
}
cout<<ans<<endl;
}
return 0;
}
1002.HDU 5612 Baby Ming and Matrix games
http://acm.hdu.edu.cn/showproblem.php?pid=5612
题意:在一个n*m的矩阵中行数和列数均为偶数的格点上有0~9之间的数字,数字之间的格点上有四则运算的符号,在矩阵上画一条不与自己相交的线,要求能形成一个合法的运算表达式,问你能否找到这样一个表达式使运算结果为给定值sun(-1e18~1e18)。另外每个矩阵上的数字个数不超过15个。
解法:比赛时候想的是状态压缩DP,将矩阵中的数字编号,dp【s】【i】表示数字集合s构成的、以第i个数字结尾的表达式的结果的集合,对于与 i 相邻的编号为 j 的数字,如果(s&(1<<j))==0,dp【s|(1<<j)】【j】=dp【s】【i】(ope)num【j】,其中ope为i与j之间的四则运算,num【j】为第j个数字的值。但是TLE。。。
其实想一想是有道理的,解题的关键是路径构成表达式,强行用集合表示肯定会TLE,因为会多出很多冗余的状态、还需要维护集合。
看题解,发现就是一个裸的DFS,比赛时候想过但是过高地估计了复杂度,题解上说数字个数不超过15个最多有14000个状态(不知道咋算的),直接dfs就好。另外运算结果可能出现小数,但是这个题数据比较菜,用double表示结果都能过(需要用eps控制精度)。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <queue>
using namespace std;
typedef long long LL;
typedef double LD;
const LD eps=1e-10;
char s[50][50];
int vis[50][50];
int dx[4]={0,1,0,-1};
int dy[4]={1,0,-1,0};
int t,n,m,Get;
LL sum;
int OK;
LD ope(LD a,LD b,char c){
if(c=='+') return a+b;
if(c=='-') return a-b;
if(c=='*') return a*b;
if(fabs(b)<=eps) {
OK=0;
return -1;
}
return a/b;
}
void dfs(LD now,int x,int y){
if(Get) return ;
vis[x][y]=1;
if(fabs(now-(LD)sum)<=eps){
Get=1;
return ;
}
for(int i=0;i<4;i++){
int xx=x+dx[i]*2,yy=y+dy[i]*2;
if(xx<n&&xx>=0&&yy<m&&yy>=0&&vis[xx][yy]==0){
OK=1;
LD New=ope(now,s[xx][yy]-'0',s[x+dx[i]][y+dy[i]]);
if(OK) dfs(New,xx,yy);
}
}
vis[x][y]=0;
return ;
}
int main (){
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
cin>>sum;
for(int i=0;i<n;i++) scanf("%s",s[i]);
Get=0;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(s[i][j]>='0'&&s[i][j]<='9'){
memset(vis,0,sizeof(vis));
dfs(s[i][j]-'0',i,j);
}
if(Get) break;
}
if(Get) break;
}
if(Get)
printf("Possible\n");
else
printf("Impossible\n");
}
return 0;
}
1003. HDU 5613 Baby Ming and Binary image
http://acm.hdu.edu.cn/showproblem.php?pid=5613
题意:就是给你一个n*m(n<=12,m<=100)的矩阵,让你恢复出他的原矩阵。原矩阵到现矩阵的方式为:其原矩阵为01矩阵,且原矩阵第一行和最后一行均为0,将其每个位置的值变为其本身和周围八个位置一共九个位置上1的个数。
解法:注意到n的个数很小,且只要知道了原矩阵第一列的01分布就可以根据给出的矩阵复原出原矩阵,再验证一下最后一列是否符合要求即可。那么我们就可以暴力枚举2^(n-2)种可能个第一列的01分布,然后逐个验证即可。(赛后改题时候出了很多细小的错误,还是练得少啊)。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <queue>
using namespace std;
int a[15][120],b[15][120],ans[15][120];
int n,m;
void print(int s){
for(int i=0;i<11;i++){
if(s&(1<<i)) printf("1");
else printf("0");
}
printf("\n");
}
int solve(int s){
//print(s);
for(int i=0;i<n-2;i++){
if(s&(1<<i))
b[i+2][1]=1;
else
b[i+2][1]=0;
}
int tot;
for(int j=2;j<=m;j++){
for(int i=2;i<n;i++){
tot=b[i-2][j-2]+b[i-2][j-1]+b[i-2][j]+
b[i-1][j-2]+b[i-1][j-1]+b[i-1][j]+
b[i][j-2]+b[i][j-1];
if(tot==a[i-1][j-1])
b[i][j]=0;
else{
if(tot==a[i-1][j-1]-1)
b[i][j]=1;
else
return 0;
}
}
}
/* for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++)
printf("%d ",b[i][j]);
printf("\n");
}*/
for(int i=1;i<=n;i++){
tot=b[i-1][m-1]+b[i-1][m]+b[i][m-1]+b[i][m]+b[i+1][m-1]+b[i+1][m];
if(tot!=a[i][m]) return 0;
}
return 1;
}
int main (){
int t;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&a[i][j]);
int GET=0;
memset(b,0,sizeof(b));
for(int i=0;i<(1<<(n-2));i++){
if(solve(i)){
GET++;
if(GET==1){
for(int j=1;j<=n;j++)
for(int k=1;k<=m;k++)
ans[j][k]=b[j][k];
}
if(GET>=2) break;
}
}
if(GET>0){
if(GET>1)
printf("Multiple\n");
else{
for(int i=1;i<=n;i++){
for(int j=1;j<m;j++)
printf("%d ",ans[i][j]);
printf("%d\n",ans[i][m]);
}
}
}
else
printf("Impossible\n");
}
return 0;
}
1004. HDU 5614 Baby Ming and Matrix tree
http://acm.hdu.edu.cn/showproblem.php?pid=5614
传说中的树链剖分,目前不会啊。。。。(留个坑)。