pku 1020 Anniversary Cake

刚开始是用dp,以每个单位格为起点,逐个放置正方形,无法放置时在回溯,开始是超时,后来是WA,找了好久也没找到错误的地方,索性换方法

在网上看到http://mrroach.blog.hexun.com/9822829_d.html的方法比较不错(在此向mrroachmrroach同志致谢!),于是就按他的方法写的代码(惭愧啊),代码如下,希望能为同样为此题困惑很久的同志解决下困难。。。请参照http://mrroach.blog.hexun.com/9822829_d.html读此代码。。。。。。

#include<iostream>
#include <stdlib.h>
#include <string.h>
using namespace std;
int min(int a,int b,int c) {return a>(b>c?c:b)?(b>c?c:b):a;}
int cut[11],n,s,maxl,minl;
int map[41];
int slove()
{
      int p=1,i,j,k;
     // for(k=1;k<=s;k++) printf("[+%d+]",map[k]);cout<<endl;
      for(k=1;k<=10;k++) if(cut[k]!=0) {minl=k;break;}
      for(k=10;k>=1;k--) if(cut[k]!=0) {maxl=k;break;}
      if(maxl==1) return 1;
      bool sign1=1;
      for(k=1;k<=s;k++) if(map[k]!=s) {sign1=0;break;}
      if(sign1) return 1;
      for(i=1;i<=s;i++)
       {
         if(map[p]==0)break;
         if(map[i]<map[p]) p=i;
       }
       int pp=p,w=1;
       bool sign=1;
       while(sign){
                     if(pp<s&&map[pp]==map[pp+1]) {w++;pp++;}
                     else sign=0;
                   }
                  // printf("([%d+%d+)",p,w);
       for(i=min(s-map[p],w,maxl);i>=minl;i--)
        {//printf("(%d)",maxl);
           if(cut[i]!=0&&p+i-1<=s){
                         for(j=p;j<p+i;j++) map[j]+=i;
                         cut[i]--;//printf("!");
                         if(slove()) return 1;
                         else {
                              cut[i]++;
                              for(j=p;j<p+i;j++) map[j]-=i;
                              for(k=1;k<=10;k++) if(cut[k]!=0) {minl=k;break;}
                              for(k=10;k>=1;k--) if(cut[k]!=0) {maxl=k;break;}
                              }
                         }                   
        }
        return 0;
}
int main()
{
    int count;
    int i,j,k;
    cin>>count;
    while(count--)
    {
      int total=0;
      bool sign=0;
      cin>>s>>n;
      memset(cut,0,sizeof(cut));
      memset(map,0,sizeof(map));
      for(i=1;i<=n;i++)
       {
         cin>>k;
         total+=(k*k);
         cut[k]++;
       }//cout<<total<<endl;
       if(s>40||total!=s*s) {printf("HUTUTU!/n");continue;}
       //for(i=1;i<=10;i++) printf("[%d]",cut[i]);
       if(slove()) printf("KHOOOOB!/n");
        else  printf("HUTUTU!/n"); 
      }
      return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值