USACO ttwo BZOJ 1625

来源:互联网 发布:mac打印出来是白纸 编辑:程序博客网 时间:2024/04/30 17:42

USACO ttwo 难度不大,挺适合练编码能力。一开始直接计算出了两个人的移动序列,但发现没有用。所以应该要用链表来存每个节点的后一个节点,然后进行枚举即可。

 

/*ID: 13917981PROG: ttwoLANG: C++*/#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <ctime>#include <vector>#include <list>#include <deque>#include <queue>#include <stack>#include <map>#include <set>#include <algorithm>#include <cmath>#define REP(i,n) for(int i=0;i<(n);i++)#define REP1(i,n) for(int i=1;i<=(n);i++)#define FOR(i,a,b) for(int i=(a);i<=(b);i++)#define CLR(x,n) memset(x,n,sizeof(x))using namespace std;/*WA 一次 忘了输出0了..*/ void setio(string name){     string in_f=name+".in";     string out_f=name+".out";     freopen(in_f.c_str(),"r",stdin);     freopen(out_f.c_str(),"w",stdout);}int gcd(int a,int b){return b==0?a:gcd(b,a%b);}struct point{int x,y,dir;point(){x=y=dir=100;}};char s[20][20];int vis[2][20][20][4]; //方向 N 0 E 1 S 2 W 3 point next[2][20][20][4];int leng[2];void get2(int x,int y,int dir,int &x1,int &y1){     if (dir==0){x1=x-1;y1=y;}     if (dir==1){x1=x;y1=y+1;}     if (dir==2){x1=x+1;y1=y;}     if (dir==3){x1=x;y1=y-1;}}bool out1(int x,int y){     return x<0 || x>9 || y<0 || y>9;}void search1(int ty,int x,int y,int dir,int len){     //printf("%d %d %d %d %d\n",ty,x,y,dir,len);     vis[ty][x][y][dir]=1;          //path[ty][len][0]=x;path[ty][len][1]=y;     int x1=0,y1=0,x2=x,y2=y,dir2=dir;     get2(x,y,dir,x1,y1);          if (s[x1][y1]=='*' || out1(x1,y1))dir2=(dir+1)%4;     else {x2=x1;y2=y1;}     point& t=next[ty][x][y][dir];     t.x=x2;t.y=y2;t.dir=dir2;          if (vis[ty][x2][y2][dir2]){leng[ty]=len;return;}          //printf("%d %d %d %d %d %d %d\n",ty,x,y,dir,t.x,t.y,t.dir);     search1(ty,x2,y2,dir2,len+1);     }char get1(){char c;do c=getchar();while(!(c=='.'||c=='*'||c=='C'||c=='F'));return c;}int main(){    setio("ttwo");    int fx,fy,cx,cy;    REP(i,10)REP(j,10) {                       s[i][j]=get1();                       if (s[i][j]=='F'){fx=i;fy=j;}                       if (s[i][j]=='C'){cx=i;cy=j;}     }    //REP(i,10){REP(j,10)printf("%c ",s[i][j]);cout<<endl;}    CLR(vis,0);    search1(0,fx,fy,0,0);    search1(1,cx,cy,0,0);    point i=next[0][fx][fy][0];//printf("%d %d %d %d %d",fx,fy,i.x,i.y,i.dir);    point j=next[1][cx][cy][0];    //printf("%d %d\n",leng[0],leng[1]);    REP(ka,leng[0]*leng[1]/gcd(leng[0],leng[1]))    {          //printf("%d %d %d %d %d %d %d\n",ka,i.x,i.y,i.dir,j.x,j.y,j.dir);          if (i.x==j.x && i.y==j.y){printf("%d\n",ka+1);return 0;}          i=next[0][i.x][i.y][i.dir];          j=next[1][j.x][j.y][j.dir];    }    cout<<0<<endl;    return 0;    //system("pause");}

BZOJ 1625 容易上当的一道题。因为休息必须要恢复到不疲劳才能继续运动,我理解成了随时休息随时继续。接下来就是dp,设d[i]是第i天时不疲劳情况下答案的最大值,则枚举休息的天数即可d[i]=d[i-2k] + a[i-2k]+..a[i-k-1] 再利用前缀和优化时间

 

#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <ctime>#include <cmath>#include <vector>#include <deque>#include <algorithm>#include <list>#include <map>#include <set>#include <queue>#include <stack>#define REP(i,n) for(int i=0;i<(n);i++)#define REP1(i,n) for(int i=1;i<=(n);i++)#define FOR(i,a,b) for (int i=(a);i<=(b);i++)#define CLR(x,n) memset(x,n,sizeof(x))using namespace std;int v[4000],w[4000],dp[15000];   int main(){    int n,m;scanf("%d%d",&n,&m);    REP1(i,n)scanf("%d%d",&w[i],&v[i]);    CLR(dp,0);    REP1(i,n) for (int j=m;j>=1;j--)    {                            if (j>=w[i]) dp[j]=max( dp[j], dp[j-w[i]]+v[i] );    }    printf("%d\n",dp[m]);    //REP1(i,n) {REP1(j,m)printf("%d ",dp[j]);cout<<endl;}    //system("pause");    return 0;}

 

原创粉丝点击