CF 358D - 358E #209 (Div. 2)

D. Dima and Hares

problem

输入n (1 ≤ n ≤ 3000) a1 a2 ... an.   b1, b2, ..., bn.   c1, c2, ..., cn

n只兔子,每只兔子喂一遍,abc分别是旁边两只都饿着一直饿着一直饱着两只都饱着的joy值,按照某种顺序喂,求最大joy和。

think

两边的情况太模糊。。我纠结了很久。。

dp[i][0]表示喂完前i-1只第i只在第i-1只之后喂

dp[i][1]表示喂完前i-1只第i只在第i-1只之前喂

答案就是dp[n+1][0]

code  

  1. int a[N], b[N], c[N], dp[N][2];  
  2.   
  3. int main ()  
  4. {  
  5.     int n;  
  6.     scanf("%d", &n);  
  7.     for(int i = 1; i <= n; ++i) scanf("%d", &a[i]);  
  8.     for(int i = 1; i <= n; ++i) scanf("%d", &b[i]);  
  9.     for(int i = 1; i <= n; ++i) scanf("%d", &c[i]);  
  10.     dp[1][0] = -100000;  
  11.     for(int i = 1; i <= n; ++i){  
  12.         dp[i+1][0] = max(dp[i][0] + b[i], dp[i][1] + a[i]);  
  13.         dp[i+1][1] = max(dp[i][0] + c[i], dp[i][1] + b[i]);  
  14.     }  
  15.     cout<<dp[n+1][0]<<endl;  
  16.     return 0;  
  17. }  


E. Dima and Kicks

   

problem

输入n m 和一个n*m的01矩阵,问是否存在“一笔画”,并且中间每笔的长度一样并且大于1

think

先判断是否有

11

11这样的,因为这样不能大于1

还有判断是否联通,还有基数点的个数最多2

code

  1. int a[1111][1111];  
  2. int vis[1111][1111];  
  3. int ans[1111];  
  4. int dx[] = {0, 0, 1, -1};  
  5. int dy[] = {-1, 1, 0, 0};  
  6. int n, m, amount;  
  7.   
  8. int gcd(int x, int y){  
  9.     return (x==0 ? y : gcd(y % x, x));  
  10. }  
  11.   
  12. int cal(int x, int y){  
  13.     int ans = 0;  
  14.     if(x > 1 && a[x-1][y]) ++ans;  
  15.     if(x < n && a[x+1][y]) ++ans;  
  16.     if(y > 1 && a[x][y-1]) ++ans;  
  17.     if(y < m && a[x][y+1]) ++ans;  
  18.     return ans;  
  19. }  
  20.   
  21. bool sq(){  
  22.     for(int i = 1; i < n; ++i)  
  23.         for(int j = 1; j < m; ++j){  
  24.             if(a[i][j]==1 && a[i+1][j]==1 && a[i][j+1]==1 && a[i+1][j+1]==1) return true;  
  25.         }  
  26.     return false;  
  27. }  
  28.   
  29. int dfs(int i,int j){  
  30.     if(i<1 || i>n || j<1 || j>m) return 0;  
  31.     if(!a[i][j] || vis[i][j]) return 0;  
  32.     vis[i][j]=true;  
  33.     return  dfs(i+1,j) + dfs(i-1,j) + dfs(i,j+1) + dfs(i,j-1) + 1;  
  34. }  
  35.   
  36. bool ou(){  
  37.     memset(vis, 0, sizeof(vis));  
  38.     for(int i = 1; i <= n; ++i){  
  39.         for(int j = 1; j <= m; ++j){  
  40.             if(a[i][j]==1){  
  41.                 if(dfs(i, j)==amount) return true;  
  42.                 else return false;  
  43.             }  
  44.         }  
  45.     }  
  46. }  
  47.   
  48. int solve(){  
  49.     memset(vis, 0, sizeof(vis));  
  50.     memset(ans, 0, sizeof(ans));  
  51.     int odd = 0;  
  52.     for(int i = 1; i <= n; ++i){  
  53.         for(int j = 1; j <= m; ++j){  
  54.             if(a[i][j]){  
  55.                 int num = cal(i, j);  
  56.                 odd += (num&1);  
  57.                 if(odd >= 3) return 0;  
  58.                 if(num == 2 && ((a[i+1][j]==1 && a[i-1][j]==1) || (a[i][j+1]==1 && a[i][j-1]==1))) continue;  
  59.                 vis[i][j] = 1;  
  60.             }  
  61.         }  
  62.     }  
  63.     int gg = 1;  
  64.     for(int i = 1; i <= n; i++){  
  65.         for(int j = 1; j <= m; ++j) if(vis[i][j]){  
  66.             for(int d = 0, k; d < 4; ++d){  
  67.                 for(k = 1; a[i+dx[d]*k][j+dy[d]*k] && !vis[i+dx[d]*k][j+dy[d]*k]; ++k);  
  68.                 if(k > 1){  
  69.                     ans[k] = 1;  
  70.                     gg = k;  
  71.                 }  
  72.             }  
  73.         }  
  74.     }  
  75.   
  76.     for(int k = max(n, m); k > 1; --k)  
  77.     if(ans[k]) gg = gcd(gg, k);  
  78.     return gg;  
  79. }  
  80.   
  81. int main(){  
  82.     amount = 0;  
  83.     scanf("%d%d", &n, &m);  
  84.     memset(a, 0, sizeof(a));  
  85.     for(int i = 1; i <= n; ++i) for(int j = 1; j <= m; amount += a[i][j], ++j) scanf("%d", &a[i][j]);  
  86.     if(sq() || !ou()){  
  87.         puts("-1");  
  88.         return 0;  
  89.     }  
  90.     int res = solve();  
  91.     if(res < 2) puts("-1");  
  92.     else{  
  93.         for(int i = 2; i < res; ++i){  
  94.             if(res % i == 0) printf("%d ", i);  
  95.         }  
  96.         printf("%d\n", res);  
  97.     }  
  98.     return 0;  
  99. }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值