USACO ttwo BZOJ 1625

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

 

/*
	ID: 13917981
	PROG: ttwo
	LANG: 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;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值