[Offer收割]编程练习赛1

做了三题,题目都比较暴力。


A题

题目链接:A题


题意:给你一个三阶的幻方,三阶幻方指的是将1~9不重复的填入一个3*3的矩阵当中,使得每一行、每一列和每一条对角线的和都是相同的。现在准备将一个三阶幻方中的一些数组抹掉(0代替),交给你来进行还原,并且希望她能够判断出究竟是不是只有一组解。

如果只有一组解,输出该三阶幻方。如果多组解,输出“Too Many”。(题目保证有解)


题解:纯暴力,枚举被抹去位置的情况,并且判重加记录就可以做出来。时间复杂度O(9!)。


代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<sstream>
#include<algorithm>
#include<vector>
#include<bitset>
#include<set>
#include<queue>
#include<stack>
#include<map>
#include<cstdlib>
#include<cmath>
#define PI 2*asin(1.0)
#define LL long long
#define pb push_back
#define pa pair<int,int>
#define clr(a,b) memset(a,b,sizeof(a))
#define lson lr<<1,l,mid
#define rson lr<<1|1,mid+1,r
#define bug(x) printf("%d++++++++++++++++++++%d\n",x,x)
#define key_value ch[ch[root][1]][0]
const int  MOD = 1000000007;
const int N = 1e5+15;
const int maxn = 450;
const int letter = 130;
const int INF = 15000000;
const double pi=acos(-1.0);
const double eps=1e-8;
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int c[20],b[20],a[20],vis[20],dis[20],sum=0;
bool solve(int x,int y,int z){
    return b[x]+b[y]+b[z]==15;
}
void dfs(int x,int f){
   b[x]=f;
   vis[f]=1;
   if(x==9){
       if(solve(1,2,3)&&solve(4,5,6)&&solve(7,8,9)&&solve(1,4,7)&&solve(2,5,8)&&solve(3,6,9)&&solve(1,5,9)&&solve(3,5,7)) {
           for(int i=1;i<=9;i++) c[i]=b[i];
           sum++;
       }
       return;
   }
     if(a[x+1]) dfs(x+1,a[x+1]);
     else for(int i=1;i<=9;i++){
            if(!vis[i]&&!dis[i]) dfs(x+1,i),vis[i]=0;
          }
}
int main(){
    for(int i=1;i<=9;i++) scanf("%d",a+i),dis[a[i]]=1;
    dfs(0,0);
    if(sum==1) {
        for(int i=1;i<=9;i++){
            if(i%3==1) printf("%d",c[i]);
            else printf(" %d",c[i]);
            if(i%3==0) printf("\n");
        }
    }
    else puts("Too Many");
    return 0;
}

B题:

题目链接:B题


题意:(中文题简单易懂)


题解:我们注意到随着缓存区K的增大,总延迟惩罚是在减少的,再看n的的大小只有100000,直接二分可做,并且可以利用优先队列维护最大值即可。

时间复杂度O(logn*logn)


代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<sstream>
#include<algorithm>
#include<vector>
#include<bitset>
#include<set>
#include<queue>
#include<stack>
#include<map>
#include<cstdlib>
#include<cmath>
#define PI 2*asin(1.0)
#define LL long long
#define pb push_back
#define pa pair<int,int>
#define clr(a,b) memset(a,b,sizeof(a))
#define lson lr<<1,l,mid
#define rson lr<<1|1,mid+1,r
#define bug(x) printf("%d++++++++++++++++++++%d\n",x,x)
#define key_value ch[ch[root][1]][0]
const int  MOD = 1000000007;
const int N = 1e5+15;
const int maxn = 450;
const int letter = 130;
const int INF = 1e17;
const double pi=acos(-1.0);
const double eps=1e-8;
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
LL n,ps,a[N];
bool solve(LL x){
    LL sum=0,vv=1;
    priority_queue<LL>q;
    while(!q.empty()) q.pop();
    for(LL i=1;i<=n;i++){
        if(q.size()<x) {
            q.push(a[i]);
        }
        else {
            sum+=vv*q.top();
            q.pop();
            vv++;
            q.push(a[i]);
        }
        if(sum>ps) return 0;
    }
    while(!q.empty()){
        sum+=vv*q.top();
        q.pop();
        vv++;
        if(sum>ps) return 0;
    }
  ///  printf("%lld %lld\n",x,sum);
    return 1;
}
int main(){
    scanf("%lld%lld",&n,&ps);
    for(int i=1;i<=n;i++) scanf("%lld",a+i);
    LL l=1,r=n;
    LL ans=INF;
    while(l<=r){
        LL mid=(l+r)/2;
        if(solve(mid)){
            ans=min(ans,mid);
            r=mid-1;
        }
        else {
            l=mid+1;
        }
    }
    if(ans!=INF)printf("%lld\n",ans);
    else puts("-1");
    return 0;
}


C题

题目链接:C题


题意:(中文题简单易懂)


题解:仔细分析下可以看出是完全背包,但是有一些要注意的。背包的容量应该为2*k,因为建筑值肯定要超过k的。而且注意特判下,当建筑值大于等于k的时候单独拿出来计算,因为假如我的建筑值为3k 4k的时候肯定是背包更新不到的,所以特判下。时间复杂度:O(q*n*k*m)。


代码:

#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<cstring>
#include<iostream>
#include<sstream>
#include<algorithm>
#include<vector>
#include<bitset>
#include<set>
#include<queue>
#include<stack>
#include<map>
#include<cstdlib>
#include<cmath>
#define PI 2*asin(1.0)
#define LL long long
#define pa pair<int,int>
#define pb push_back
#define clr(a,b) memset(a,b,sizeof(a))
#define lson lr<<1,l,mid
#define rson lr<<1|1,mid+1,r
#define bug(x) printf("%d++++++++++++++++++++%d\n",x,x)
const int  MOD = 1000000007;
const int N = 100+15;
const int maxn = 2e4 + 14;
const int INF = 1e17;
const int letter = 130;
const double pi=acos(-1.0);
const double eps=1e-10;
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int tc;
int n,m,k;
LL a[N],b[N],dp[maxn],t;
int main(){
    scanf("%d",&tc);
    while(tc--){
        LL sum=0;
        int flag=0;
        scanf("%d%d%d%lld",&n,&m,&k,&t);
        for(int i=1;i<=m;i++) scanf("%lld",&a[i]);
        for(int i=1;i<=m;i++) scanf("%lld",&b[i]);
        for(int i=1;i<=n;i++){
                LL ans=INF;
                for(int j=1;j<=2*k;j++) dp[j]=INF;
                for(int j=1;j<=m;j++){
                    if(b[j]==0) continue;
                    if(b[j]>=k) {
                        ans=min(ans,a[j]);
                        continue;
                    }
                    for(int x=b[j];x<=2*k;x++) dp[x]=min(dp[x-b[j]]+a[j],dp[x]);
                }
                for(int j=k;j<=2*k;j++) ans=min(ans,dp[j]);
                for(int j=1;j<=m;j++) b[j]/=t;
                if(ans==INF) {
                    flag=1;
                    break;
                }
                sum+=ans;

        }
        if(flag) puts("No Answer");
        else printf("%lld\n",sum);
    }
    return 0;
}


你可能感兴趣的:(编程,搜索,二分,完全背包)