SDUT_2012省赛选拔赛3

http://acm.hdu.edu.cn/webcontest/contest_show.php?cid=1887

1001:将一个数转化成-2进制的数,同样对这个数模-2倒取于,分清正数与负数,两种不同的情况;

View Code

1002:DFS;给的数据很小所以暴力就可以过,首先求出n个字符串的全排列,然后检查是否可以连接,求最后的长度,枚举出最小的值。在这里又犯了个不可原谅的小错误。。唉。细心。。

View Code

1003:字典树;每个点减去空格的ASSIC码,(应为空格的ASIIC吗最小),然后插入,查找。

View Code

1004:贪心;可以想象成上升沿与下降沿,求顶峰的值,中间的细节也要注意。

View Code

1005:DP: 自己对dp的感觉实在是肤浅,以后要加强对dp的练习,虎哥给讲的:因为要尽量保持牛与牛之间的距离最大并且移动步数最少且牛语牛之间的距离去{d,d + 1}所以第一头牛肯定在0位置,第n头牛在L位置。 dp[i][j]表示将第i头牛放在第j个位置后整个过程一共移动了多少步(包括1,2,....i - 1的移动步数),

然后有dp[i][j] = dp[i - 1][j - d] + abs(pos[i] - j) 如果可以取d +1 则又有 dp[i][j] = min(dp[i - 1][j] ,dp[i - 1][j - d1] + abs(pos[i] - j))

View Code
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#define maxn 100005
#define inf 99999999
using namespace std;

int dp[2][maxn],pos[maxn];
int n,L;
int d,d1;

void getlr(int pos,int &l,int &r)
{
    if (pos < n)
    {
        l = d*(pos - 1);
        if (d1 != -1 && L - (d1*(n - pos)) > l)
        l = L - (d1*(n - pos)) ;
        r = L - d*(n - pos);
        if (d1 != -1 && (d1*(pos -1)) < r)
        r = (d1*(pos -1));
    }
    else
    {
        l = r = L;
    }
}
int main()
{
   int i,j;
   scanf("%d%d",&n,&L);
   for (i = 1; i <= n; ++i) scanf("%d",&pos[i]);
   for (i = 0; i < 2; ++i)
   {
       for (j = 0; j < maxn; ++j)
       dp[i][j] = inf;
   }
   d = L/(n - 1);
   if (L%(n - 1) == 0) d1 = -1;//如果不能整除
   else d1 = d + 1;
   dp[1][0] = abs(pos[1] - 0);//首先求出第一头牛移动的步数
   int l,r;
   for (i = 2; i <= n; ++i)
   {
       getlr(i,l,r);//得到第i头牛的移动范围
       //printf("%d %d\n",l,r);
       for (j = l; j <= r; ++j)
       {
           dp[i%2][j] = dp[(i - 1)%2][j - d] + abs(pos[i] - j);
           if (d1 != -1 && j - d1 >= 0)
           dp[i%2][j] = min(dp[i%2][j],dp[(i - 1)%2][j - d1] + abs(pos[i] - j));
       }
       if (i > 3)//例如求4时,求2的构成会对4的一些长生影响,
       {
           int l1,r1;
           getlr(i - 2,l1,r1);
           for (j = l1; j <= r1; ++j)
           {
               if (j < l || j > r)
               dp[i%2][j] = inf;
           }
       }
   }
   printf("%d\n",dp[n%2][L]);
    return 0;
}

 

1006:DFS:枚举每个碗的状态,要么是1,要么是0,中间自己出了一个很傻比的错误,哎》》不够细心啊。

View Code
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#define maxn 22
using namespace std;

int a[maxn];
int b[maxn];
int ans;

bool isok()
{
    for (int i = 0; i < 20; ++i)
    {
        if (a[i] != b[i])
        return false;
    }
    return true;
}

void change(int x)
{
    x--;//就是这里除了问题让我贡献了好几次wa不够细心
    if (x >= 0 && x < 20)
    b[x] ^= 1;
    if (x - 1 >= 0)
    b[x -1] ^= 1;
    if (x + 1 < 20)
    b[x + 1] ^= 1;
}
void dfs(int num,int ct)
{
    if (isok())
    {
        if (ct < ans) ans = ct;
        return ;
    }
    if (ct > ans) return;
    if (num >= 20) return;
    for (int i = 0; i < 2; ++i)
    {
        if (i == 1)
        {
            change(num + 1);
            dfs(num + 1,ct + 1);
            change(num + 1);
        }
        else
        {
            dfs(num + 1,ct);
        }
    }
}
int main()
{
    //freopen("in.txt","r",stdin);
    int i;
    ans = 99999999;
    for (i = 0; i < 20; ++i)
    {
        scanf("%d",&a[i]);
        b[i] = 0;
    }
    for (i = 0; i < 2; ++i)
    {
        if  (i == 1)
        {
            change(1);
            dfs(1,1);
            change(1);
        }
        else
        {
            dfs(1,0);
        }
    }
    printf("%d\n",ans);
}



posted @ 2012-04-09 22:01  E_star  阅读(199)  评论(0编辑  收藏  举报